Dependency injection 注入实例化无法控制的类的最佳方法是什么?
我是Guice的新手,所以希望这不是一个明显的问题 我正在处理一个框架,它使用反射动态实例化我的一个应用程序类(我们称之为Dependency injection 注入实例化无法控制的类的最佳方法是什么?,dependency-injection,guice,code-migration,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?
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实现I{
公共C(){
//这个ctor是由框架调用的,所以不能在这里使用DI?
}
公共无效初始化(){
//这是f/w将调用的后实例化挂钩
}
私有无效m(){
Dependency d=Dependency.getInstance();
d、 doSmth();
}
}
我希望C
使用DI获取依赖关系。在这里,依赖关系
显然是一个单例,但通常情况下不必如此
我已经提出了两种可能的解决方案,这两种方案感觉都不整洁,所以我想我应该问问专家:
静态注入。我很难看出这是如何在服务定位器反模式的基础上大幅改进的-我最终得到了可以在外部操纵的非最终静态字段。。。嗯
框架支持一个钩子,用于C
在实例化后初始化自身(上面显示的initialize()
方法)。此方法可以使用setter注入自注入新创建的实例
对于2,我想这意味着更多的外部可更改性,但对于单元测试之类的事情,至少会更明确地暴露依赖性。问题是:在这种情况下,我如何获得Guice注入器(除了依赖另一个服务定位器之外)?我也读过(并且倾向于同意)在整个应用程序代码中明确引用注入器是一种可疑的做法
非常感谢你的洞察力
非常感谢,
Christian您可以尝试将提供程序静态注入到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();
...
}
}
公共类C实现I{
@注入静态提供者dep1Provider;
@注入静态提供者dep2Provider;
...
公共无效初始化(){
Dep1 Dep1=dep1Provider.get();
Dep2 Dep2=dep2Provider.get();
...
}
}
如果您通过静态变量和静态访问器方法使Guice injector可用,您可以这样解决:
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();
}
}
静态调用有点反模式,如果您愿意使用代码编织或编译后步骤的解决方案,您可以通过一个简单的注释来消除这种依赖性,该注释负责后构造函数注入。这样,即使没有初始化方法,也可以注入所有对象。您可以在此处找到此示例:
谢谢Jesse,这听起来与我上面的选项1相似;尽管我认为使用提供程序
s确实使模式更通用。感谢Kdeveloper,这更像原始问题中列出的选项2,并提供了一个有用的高级技术演示,可用于缓解对全局状态的需要(即:第一个示例中的注入器)。我的直觉是,就代码的可维护性而言,补救措施(DI)开始感觉比疾病(服务定位器“反模式”)稍差一些,但有趣的是,与静态注入解决方案相比,结果代码的可测试性得到了改善。
@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();
}
}