请记住,在任何注入发生之前,所有configure
方法都会配置所有绑定。也就是说,有几件事:Injector
将属性绑定@Named
到单个Properties
实例的内容非常有用,有一种Names.bindProperties(...)
方法可以自动为您完成。唯一的技巧是您需要Properties
在运行时拥有实例configure()
。
如果它们同时可用,则不必担心将属性绑定到一个模块中并将应用程序绑定到另一个模块中。只要它们都进入同一个Injector
,Guice就会将它们全部组合起来,让它们满足彼此的依赖关系。
提供者可以返回不同的实例,并且通常会这样做——但你是对的,它不会帮助你区分键。如果直接注入 Properties 实例太难看,可以考虑创建一个轻量级工厂:
public class ConfigOracle {
@Inject private Properties properties;
public String getAsString(String key) { ... }
public int getAsInt(String key) { ... }
}
public class SomeConfigUser {
@Inject private ConfigOracle configOracle;
public void doStuff() {
doStuffBasedOn(configOracle.getAsString("my.properties.key"));
}
}
您永远不需要将 a Binder
(或其他任何东西)注入到模块中。
- 如果实现
Module
,binder
将是 的参数configure()
。如果您AbstractModule
按照应有的方式进行扩展,只需调用该binder()
方法即可。
- 如果需要,您可以通过构造函数参数将依赖项传递给模块,这(就我而言)是模块应该改变它们创建的绑定的唯一方法。
- 没有理由你不能通过 Injector 创建一个 Module,但你必须首先拥有一个 Injector,听起来你只是想逃避只有一个。
- 如果您需要注入器中的其他实例,您始终可以
Provider
使用字段/方法/构造函数编写实现@Inject
,甚至可以在@Provides
方法中接收参数(将自动填充依赖项)。
总的来说,我仍然喜欢子注入器方法(感谢链接和对我之前回答的赞美!),它最适合您的“基于注入实例的动态绑定”描述,并且实际上就是这么简单:
class PropertiesModule extends AbstractModule {
Properties properties;
PropertiesModule(Properties properties) {
this.properties = properties;
}
@Override public void configure() {
Names.bindProperties(binder(), properties);
}
}
Injector oldInjector = Guice.createInjector(allYourOtherModules);
Module myModule = new PropertiesModule(oldInjector.get(Properties.class));
Injector injector = oldInjector.createChildInjector(myModule);