我想创建一个动态绑定(bind)实例到命名注释的模块。用例是我想自动将配置中的值与属性文件中的键绑定(bind)为 @Named 值。
但是配置绑定(bind)在不同的模块中,所以我需要注入(inject)配置。我看过的解决方案是:
在 configure() 方法中绑定(bind)。 此方法未注入(inject),无法获取基础配置。
使用提供者/@Provides。 提供者只绑定(bind)一个实例。
使用 MultiBinder。 我的用例与此扩展提供的用例略有不同。多重绑定(bind)允许您分别绑定(bind)多个实例,然后将它们作为更复杂的包含类型的 Collection 注入(inject)。我想分别绑定(bind)每个实例,并通过唯一可识别的方式让它们在后面注入(inject)。
使用 childInjector。 不幸的是,如果不对现有代码进行大量修改,这是不可能的。 This answer很好地描述了如何以这种方式解决这个问题。
以某种方式注入(inject) Binder 。 (我开始变得有点黑客) Guice 允许注入(inject) Injector 供以后使用,我尝试通过 @Provides 方法将 Binder 注入(inject) Module,然后直接使用 binder 在方法中进行多次绑定(bind)。 Guice 不会注入(inject) Binder 。
最佳答案
请记住,所有 configure
方法在 之前配置所有 Injector
中的绑定(bind)任何注入(inject)都可能发生。也就是说,有几件事:
将
@Named
属性绑定(bind)到单个Properties
实例的内容非常有用,有一个Names.bindProperties(...)
自动为您完成的方法。唯一的技巧是您需要在configure()
运行时拥有Properties
实例。如果它们同时可用,则不必担心在一个模块中绑定(bind)属性并在另一个模块中绑定(bind)应用程序。只要它们都进入同一个
Injector
,Guice 就会将它们全部组合起来,让它们满足彼此的依赖关系。提供程序可以返回不同的实例,而且通常会返回不同的实例——但您是对的,它不会帮助您区分键。如果直接注入(inject) 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")); } }
您永远不需要将
Binder
(或其他任何东西)注入(inject)到模块中。- 如果您实现
模块
,binder
将是configure()
的参数。如果您按需要扩展AbstractModule
,只需调用binder()
方法即可。 - 如果需要,您可以通过构造函数参数将依赖项传递给模块,这(就我而言)是模块应该改变它们创建的绑定(bind)的唯一方法。
- 您没有理由不能通过注入(inject)器创建模块,但您必须首先拥有一个注入(inject)器,这听起来像是您试图只拥有一个注入(inject)器。
- 如果您需要 Injector 的其他实例,您始终可以使用
@Inject
字段/方法/构造函数编写Provider
实现,甚至可以在@Provides
方法(将是 filled in with dependencies automatically )。
- 如果您实现
总的来说,我仍然喜欢子注入(inject)器方法(感谢您提供的链接和对我之前回答的赞美!),它最适合您的“基于注入(inject)实例的动态绑定(bind)”描述,而且字面意思就是这么简单:
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);
关于java - 如何在需要注入(inject)实例的 Guice 中进行动态绑定(bind)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13242957/