【问题标题】:How inject 3 instances of same type with different dependence by Guice?Guice如何注入具有不同依赖关系的3个相同类型的实例?
【发布时间】:2015-02-15 05:29:02
【问题描述】:

我正在使用 Guice 来管理我的班级依赖性。我有一个 LogicHandler 类,它依赖于几个 Components 类。

  public interface LogicHandler {
      private Component component1;
      private Component component2;
      private Component component3;
  }

  public interface Component {
      public String doWork();
  }

我将拥有 3 个 LoigcHanlder 实例。使用哪个实例将在运行时决定。每个实例都有不同的组件实现,所有实现都是预定义的。

如果我使用 spring DI,xml 配置将如下所示:

<bean id="handler1" class="org.sample.handlers.DefaultHanlder">
  <property name="component1" ref="componentImplementationA" />
  <property name="component2" ref="componentImplementationB" />
  <property name="component3" ref="componentImplementationC" />
</bean>

<bean id="handler2" class="org.sample.handlers.DefaultHanlder">
  <property name="component1" ref="componentImplementationD" />
  <property name="component2" ref="componentImplementationE" />
  <property name="component3" ref="componentImplementationF" />
</bean>

<bean id="handler3" class="org.sample.handlers.DefaultHanlder">
  <property name="component1" ref="componentImplementationG" />
  <property name="component2" ref="componentImplementationH" />
  <property name="component3" ref="componentImplementationI" />
</bean>

注意:所有处理程序均由 DefaultHanlder 实现。

根据某些参数使用哪个处理程序实例。

【问题讨论】:

    标签: spring dependency-injection guice guice-3


    【解决方案1】:

    假设我正确理解了您的问题,您希望根据特定参数选择特定的具体实现进行绑定。一种方法是创建一个模块,该模块将决定绑定哪个模块所需的参数作为构造函数。绑定特定具体实现的逻辑将在模块的bind 方法中。例如

    public class YourModule extends AbstractModule {
    
    Parameters settings;
    
    public YourModule(Parameters settings) {
        this.settings = settings;
    }
    
    @Override
    protected void configure() {
       if(settings.val == 1) {
          bind(DefaultHanlder.class).toInstance(ComponentA.class);
       } else if(settings.val == 2) {
          bind(DefaultHanlder.class).toInstance(ComponentB.class);
       }
       .
       .
       .
    }
    

    创建注入器时,请使用YourModule 模块,以便正确接线。然后,注入器应该为DefaultHanlder 注入正确的具体类,而您的客户端代码不知道如何选择正确的具体实现。

    可能还有其他方法可以做到这一点(例如 AssistedInjection 也可能有效),但使用单独的模块非常简单。

    【讨论】:

    • 这允许在运行时进行选择,但只能选择一次(另外,通常最好避免的模块中的条件逻辑)。 AssistedInjection 确实是一个更好的选择,因为 @Assisted 工厂允许在运行时重复进行选择,根据需要多次。
    • 确实这种方法只适用一次。如果您需要在工作流程中多次生成具有不同配置的注入对象,那么辅助注入非常适合此操作。但是,如果您正在执行诸如基于配置参数引导注入器之类的操作,那么我认为在模块中包含条件逻辑就可以了。恕我直言,这是非常明确且易于理解的,并且维护方面比辅助注入工作所需的基础架构要清晰得多。
    【解决方案2】:

    使用限定符(例如 @Named("handler1"))并显式绑定您的实例。

     bind(Component.class).annotatedWith(Names.named("handler1").toInstance(...);
    

    【讨论】:

    • 如果您希望在一个组件中静态声明多个实例并在一个组件中单独使用,这将对您有所帮助。但是,您必须在编译时选择要使用的具体实例,或者有一个控制结构来选择正确的具体实现,如果您对特定接口进行了编码,这并不理想。听起来 OP 想知道的是如何根据一些运行时参数有选择地绑定特定的实现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-10
    • 1970-01-01
    • 1970-01-01
    • 2021-08-25
    • 1970-01-01
    • 1970-01-01
    • 2014-01-02
    相关资源
    最近更新 更多