情况:我需要在某些FooClass
中进行延迟依赖实例化,所以我将Injector
作为构造函数参数传递给类。
private final Injector m_injector;
public FooClass(@Named("FooInjector") Injector injector) {
m_injector = injector;
}
但是guice不允许绑定核心类(注入器,模块等)。解决方案是什么?
答案 0 :(得分:28)
您不应该直接使用Injector
。而是传递Provider<FooClass>
。此外,您应该在使用FooClass
的地方注入提供程序。
private final Provider<FooClass> provider;
@Inject
public ClassWhereFooIsUsed(Provider<FooClass> provider) {
this.provider = provider;
}
.... somewhere else
FooClass f = provider.get(); // This is lazy
答案 1 :(得分:12)
正如其他人已经回答的那样,你可以简单地使用@Inject Injector
,因为Guice定义了绑定本身。
通常,您的应用只需要一个Injector
,静态变量是一种更容易存储和访问单例的方法,而不是注入它。在我们的网络应用中,我们使用stripes-guicer并在需要时从其静态方法Injector
获取GuiceInjectorFactory.getInjector()
(例如,在我们的Hibernate拦截器中)。
我对“你不应该直接使用注射器”的建议感到有些困惑。除了通过调用injector.getInstance()
或injector.injectMembers()
之外,我还能如何注入实例?没有办法。是的,您可以定义Provider方法,但除非在某处,某些东西使用Injector,否则它们永远不会被调用。是的,有些模块使用Injector
为您ServletModule;您必须自己创建Injector
,但之后可以将其留给ServletModule
。
因此,在某些情况下,您可以避免直接使用Injector
,但这并不意味着您“不应该”使用它。如果您在没有任何可选模块的情况下单独使用Guice,那么您“应该”在整个地方使用Injector
,因为没有其他方法可以触发注入。 (我认为花费一整天在框架内编写代码的开发人员有时会忘记某些人实际实例化自己的对象。)
答案 2 :(得分:8)
正如@gpampara所说,Provider<T>
应该用于延迟/可选的初始化。另外,正如我在回答您的其他问题时所说,在几乎所有情况下,您应该避免在代码中引用Injector
。
也就是说,在由Guice创建的类中,只需通过声明Injector
的依赖关系就可以注入创建对象的Injector
。 Injector
可自动进行注射,无需声明任何绑定。
如果您注射Injector
,您应该考虑为什么要这样做。为什么不直接声明类所依赖的实际接口/类的依赖?向构造函数添加新的依赖项同样容易,因为它通过代码中的其他位置Injector
检索某个依赖项的实例,并且使代码更容易理解。
答案 3 :(得分:2)
您可能的参数不应该注入Injector
的实例是非常有效的,但与任何规则一样都有例外。
我有一个工厂类,它接受需要提供实例的类引用。这些实例不一定是已知的(实际上,它们是,但有很多,可能还有更多)所以我不能为所有实例提供提供者。
public class ThingFactory {
private Injector injector;
@Inject
ThingFactory(Injector injector) {
this.injector = injector;
}
public <T> T getInstance(Class<T> aClass) {
return injector.getInstance(aClass);
}
}
我的应用程序中真正的类正在扩展并覆盖另一个类 - 这就是为什么这个类基本上是Guice的一个直通。