class A {
public A() {
}
}
class B {
@Inject
@Named("A")
private A a;
public B() {
}
public A getA() {
return a;
}
}
class AModule extends AbstractModule {
@Override
protected void configure() {
}
@Provides
@Singleton
@Named("A")
public A providesA() {
return new A();
}
}
我们这样做:
AModule module = new AModule();
Injector injector = Guice.createInjector(module);
B b = injector.getInstance(B.class);
System.out.println(sample.getA());
但是我们有许多以A作为依赖关系的类,我们不希望每次创建实例时都添加此代码。
那么,有没有办法在创建B的实例时自动注入A的实例?
答案 0 :(得分:2)
创建与您在问题中建议的顶级注射器一样(通常)不正确。注入器创建很昂贵,一旦Guice计算了依赖关系图,您就不需要再次计算它。一般来说,您的应用程序中应该有一个顶级注射器,而任何其他注射器都是"儿童注射器"或者是一个单独的和不相关的对象图的一部分。
从最差"顺序来看最好的":
如果要将DI引入许多现有代码或遗留代码中,那么将Injector存储到可公开访问的对象中可能很诱人。
public class InjectorHolder() {
private InjectorHolder() {} // Not instantiable
private static Injector injector;
public static void initializeInjector() {
injector = Guice.createInjector(new AModule(), new BModule(), andSoOn());
}
public static Injector get() {
return injector;
}
public static B getB() {
return injector.getInstance(B.class);
}
}
此时,您可以从目前已迁移的应用部分中拨打InjectorHolder.get().getInstance(B.class)
或InjectorHolder.getB()
。请注意,这可能很难测试,并且直接依赖于整个应用程序中的Guice - 这两者都不理想。
Guice提供a few features for static injection,特别是方法调用requestStaticInjection(Class... types)
。通过在模块中调用它,Guice将在创建注入器后立即注入具有@Inject
注释的静态成员。
public class StaticBModule extends AbstractModule() {
@Override public void configure() { requestStaticInjection(BFactory.class); }
}
public class BFactory() {
@Inject @Named("B") private static Provider<B> bProvider;
public B get() {
return bProvider.get();
}
}
现在您可以拨打new BFactory().get()
而不是new B()
,并且它会全部转到同一个注射器。当然,如果您将new B()
放入static Provider<A>
类并为此请求静态注入,或者您可以将B
保留为实例,则也可以允许BFactory
并在测试期间替换它以发出所需的B
个实例。此时,您可能只需要改进调用new BFactory()
而不是包含static Provider<B>
的类,并让它们静态注入,然后将它们迁移,直到您有完整的DI解决方案(如下所述)。
您也可以咨询this SO question,其中有一个例子。
您已向我们展示了A
和B
,但可能其他一些班级C
使用了B
的许多实例,也许YourApplication
(其中包含您的静态main
方法)使用C
。您可以使用Guice创建YourApplication
或C
的实例,然后C
可以包含注入的Provider<B> bFactory
。然后,您可以调用new B()
来创建尽可能多的bFactory.get()
个实例,而不是致电B
。
通过这种方式,您的类完全取决于它们所依赖的内容,没有静态或对Guice的引用,而不是顶层。