注入实例化无法控制的类的最佳方法是什么?

时间:2011-03-16 16:37:24

标签: dependency-injection guice code-migration

我对Guice很新,所以希望这不是一个明显的问题......

我正在处理一个框架,它使用反射动态实例化我的一个应用程序类(让我们称之为C),所以我无法控制它的实例化。此外,在框架对其进行即时化后,我无法轻松访问新创建的C。这是C的样子:

    public class C implements I {

        public C() {
            // this ctor is invoked by the framework so can't use DI here?
        }        

        public void initialize() {
            // this is a post instantiation hook which the f/w will invoke
        }

        private void m() {
            Dependency d = Dependency.getInstance();
            d.doSmth();
        }
    }

我希望C使用DI获取Dependency。这里Dependency显然是一个单身人士,但通常情况并非如此。

我想出了两个可能的解决方案,两者都感觉不是很整洁,所以我想我会问专家:

  1. 静电注射。我很难看到它如何在服务定位器反模式上大幅改善 - 我最终得到了非最终静态字段,可以在外部操作...嗯。

  2. 框架支持C的挂钩,以便在实例化后初始化自身(上面显示的initialize()方法)。此方法可以使用setter注入自行注入新创建的实例。

  3. 有了2,我猜这意味着更多的外部可变性,但至少会对单元测试等事情更明确地暴露出依赖性。麻烦的是:在这种情况下如何获得Guice Injector(不依赖于另一个服务定位器)?我也读过(并且倾向于同意)在整个应用程序代码中明确提到注入器是可疑的实践。

    非常感谢您的见解。

    非常感谢,
    基督教

2 个答案:

答案 0 :(得分:2)

你可以尝试静态地将提供者注入C.静态注入更难以测试。但是提供商使Guice能够热切地验证你的依赖关系,同时懒洋洋地创建它们。

public class C implements I {
  @Inject static Provider<Dep1> dep1Provider;
  @Inject static Provider<Dep2> dep2Provider;

  ...

  public void initialize() {
    Dep1 dep1 = dep1Provider.get();
    Dep2 dep2 = dep2Provider.get();
    ...
  }
}

答案 1 :(得分:1)

如果您通过静态变量和静态访问器方法使Guice注入器可用,您可以像这样解决它:

public class C implements I {

    public C() {
        // this ctor is invoked by the framework, you can't do injection here.
    }        

    public void initialize() {
        MyGuice.getInjector().inject(this);
    }

    @Inject
    protected void init(Dep1 dep1, Dep2 dep2) {
        this.dep1 = dep1;
        this.dep2 = dep2;
    }

    private void m() {
        dept1.doSmth();
    }
}

静态调用有点反模式,如果您愿意使用代码编织或后编译步骤的解决方案,则可以使用简单的注释来删除该依赖项,该注释负责后构造函数注入。这样,即使没有初始化方法,也可以注入所有对象。你可以在这里找到一个例子:How to inject model object with AspectJ

@Configurable
public class C implements I {

    public C() {
        // this ctor is invoked by the framework, you can't do injection here.
    }        

    @Inject
    protected void init(Dep1 dep1, Dep2 dep2) {
        this.dep1 = dep1;
        this.dep2 = dep2;
    }

    private void m() {
        dept1.doSmth();
    }
}
相关问题