java - 如何在需要注入(inject)实例的 Guice 中进行动态绑定(bind)?

标签 java dynamic configuration guice

我想创建一个动态绑定(bind)实例到命名注释的模块。用例是我想自动将配置中的值与属性文件中的键绑定(bind)为 @Named 值。

但是配置绑定(bind)在不同的模块中,所以我需要注入(inject)配置。我看过的解决方案是:

  1. 在 configure() 方法中绑定(bind)。 此方法未注入(inject),无法获取基础配置。

  2. 使用提供者/@Provides。 提供者只绑定(bind)一个实例。

  3. 使用 MultiBinder。 我的用例与此扩展提供的用例略有不同。多重绑定(bind)允许您分别绑定(bind)多个实例,然后将它们作为更复杂的包含类型的 Collection 注入(inject)。我想分别绑定(bind)每个实例,并通过唯一可识别的方式让它们在后面注入(inject)。

  4. 使用 childInjector。 不幸的是,如果不对现有代码进行大量修改,这是不可能的。 This answer很好地描述了如何以这种方式解决这个问题。

  5. 以某种方式注入(inject) Binder 。 (我开始变得有点黑客) Guice 允许注入(inject) Injector 供以后使用,我尝试通过 @Provides 方法将 Binder 注入(inject) Module,然后直接使用 binder 在方法中进行多次绑定(bind)。 Guice 不会注入(inject) Binder 。

最佳答案

请记住,所有 configure 方法在 之前配置所有 Injector 中的绑定(bind)任何注入(inject)都可能发生。也就是说,有几件事:

  1. @Named 属性绑定(bind)到单个 Properties 实例的内容非常有用,有一个 Names.bindProperties(...)自动为您完成的方法。唯一的技巧是您需要在 configure() 运行时拥有 Properties 实例。

    如果它们同时可用,则不必担心在一个模块中绑定(bind)属性并在另一个模块中绑定(bind)应用程序。只要它们都进入同一个 Injector,Guice 就会将它们全部组合起来,让它们满足彼此的依赖关系。

  2. 提供程序可以返回不同的实例,而且通常会返回不同的实例——但您是对的,它不会帮助您区分键。如果直接注入(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"));
      }
    }
    
  3. 您永远不需要将 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/

相关文章:

c++ - 在动态链接中,.exe更新时如何知道去哪里搜索库?

c# - InternalsVisibleTo 用于动态生成的程序集,但具有强大的命名

Windows 10 通过鼠标悬停延迟激活窗口?

java - 通过 telnet 高效地运行文本图形

javascript - 在 Javascript 中是否可以创建具有动态(未确定)属性/成员的对象?

configuration - 如何为多个主机头配置 Web Api 自托管

java - 如何配置 Log4J2

java - 如何将 "Set functions"(例如removeAll和addAll)从Java转换为C++?可以使用删除或插入来完成吗?

java - 如何检测文件类型的表单输入元素是否为空

java - android中20秒后终止无限循环