在其模块中访问Guice注入器?
我正在扩展Guice的AbstractModule
,在扩展类中,我需要访问Guice的注入器。 这可能,如果是的话,怎么样?
这是一个不寻常的要求。 模块更像是配置文件而不是逻辑文件:读取模块以创建注入器,然后一旦创建注入器,模块就完成了它的工作。 对于一个简单的模块,在模块准备好被丢弃之前,注入器实际上不存在。
在任何情况下,您应该通常请求Provider
,而不是请求Injector获取类X. Guice将为X
, Provider
或@Provides X
任何绑定注入X
或Provider
,因此您几乎总能执行此操作。 也就是说,注入Injector将允许您reflection性地获取实例,或者检查Injector的绑定(等)。
以下是一些需要从模块中访问Injector的有效原因/设计:
在@Provides
方法中:
模块可以包含使用@Provides
注释的方法中的迷你提供程序。 请记住, Injector
是可Injector
的 :如果您需要其中一种方法中的Injector,您可以将其作为参数接受:
public class OneModule extends AbstractModule { @Override public void configure() { /* ... */ } @Provides YourDependency getYourDependency(Injector injector) { return injector.getInstance(Class.forName(yourDependencyName)); } @Provides Something getSomething(SomethingImpl something) { return initialize(something); // preferred: only ask for what you need } @Provides SomethingElse getSomethingElse(Provider thingProvider) { return new SomethingElse(thingProvider); // asking for a provider works too } }
要在configure()中获取提供程序:
AbstractModules正是出于这个原因公开了getProvider()
,但是如果在注入器准备好提供它之前调用该Provider上的get()
(例如在配置时),则会出现错误:
public class TwoModule extends AbstractModule { @Override public void configure() { bind(Thingy.class).toInstance( new MyThingy(8675309, getProvider(Another.class))); } }
您可以调用getProvider(Injector.class)
但我不知道它是否有效,我不知道您为什么要这样做。
要在configure()中获取实例:
这是一个坏主意; 在运行所有配置方法之前,Guice尚未准备好提供实例。 您可以获得的最接近的是使用其他模块创建子Injector并将其传递到此模块,但即使这样也很少需要。
public class MainClass { public static void main(String[] args) { Injector firstStage = Guice.createInjector(new OtherModule1(), new OtherModule2()); // An alternative design would @Inject-annotate fields in ThreeModule // and get it from firstStage, but that's nonstandard and may be confusing. Injector secondStage = firstStage.createChildInjector(new ThreeModule(firstStage)); } } public class ThreeModule extends AbstractModule { private final Injector otherInjector; public ThreeModule(Injector otherInjector) { this.otherInjector = otherInjector; } @Override public void configure() { bindStuffBasedOn(otherInjector); } }