Guice/DI和混合注入以及在运行时传入的参数

Liv*_*Liv 7 java dependency-injection guice

我有一种情况,当我初始化我的一些类时,我需要注入一些字段(例如对工厂等的引用),而其他一些是动态的并在运行时创建(例如用户名等).如何使用GUICE框架构造此类对象?简单地注释我需要注入的字段@Inject不起作用,因为在使用构造函数创建对象时似乎没有设置它们.例如:

class C {
   @Inject
   private FactoryClass toBeInjected;

   private ConfigurationField passedIn;

   public C(ConfigurationField passedIn) {
      this.passedIn = passedIn;
   }
}
Run Code Online (Sandbox Code Playgroud)

如果我的理解是正确的(我可能是错的),我正在创建一个新的Cvia 实例new而不是通过Guice 的事实意味着不会发生注入.我确实需要在构造函数中传递这些参数,但也需要注入一些字段 - 所以我该如何解决这个问题?

Jef*_*ica 6

专门匹配“混合注入和传递的参数”的功能是辅助注入

class C {
  // Guice will automatically create an implementation of this interface.
  // This can be defined anywhere, but I like putting it in the class itself.
  interface Factory {
    C create(ConfigurationField passedIn);
  }

  @Inject
  private FactoryClass toBeInjected;

  private ConfigurationField passedIn;
  private SomeOtherDepIfYoudLike otherDep;

  @Inject public C(@Assisted ConfigurationField passedIn,
      SomeOtherDepIfYoudLike otherDep) {
    this.passedIn = passedIn;
    this.otherDep = otherDep;
  }
}
Run Code Online (Sandbox Code Playgroud)

现在在您的模块中:

@Override public void configure() {
  install(new FactoryModuleBuilder().build(C.Factory.class));
}
Run Code Online (Sandbox Code Playgroud)

现在,当有人想要创建一个 C 时,他们可以避免直接调用构造函数;相反,他们注入一个 C.Factory,向其中传递他们选择的 ConfigurationField 实例,并接收一个完全构造的、完全注入的 C 实例。(与大多数设计良好的 DI 对象一样,它们可以直接调用构造函数。)

请注意,此设计在以下几个方面特别有用:

  • 您可以使用构造函数注入,将所有字段视为最终字段,并将对象视为不可变。
  • 如果您完全坚持使用构造函数注入,您的对象将永远不会处于部分初始化状态,并且您的 API 保持简单(调用构造函数并且您的对象已准备就绪)。
  • 为了进行测试,您可以编写任何实现C.Factory并让它返回您想要的任何实例。这可以包括 C 或其工厂的测试替身:您手动或使用 Mockito、EasyMock、JMock 或任何其他模拟框架创建的 Fakes、mocks 或 spies。