如何通过 Guice 在嵌套模块场景中注入具有相同接口的不同实现的列表?

How to inject a list with different implementations of the same interface in a nested module scenario via Guice?

有一个接口 DCE,它由 class DCEImpl 实现,它具有依赖性,例如,字符串 S,它通过其构造函数获得。

S的宇宙是有限的,比如说S只能取值{'A','B','C'}。

已有一个 Guice 模块在其构造函数中接受 S 的值,然后将接口 DCE 绑定到 DCEImpl 的正确初始化版本。

public class DCEModule extends AbstractModule {
    private final String s;
    public DCEModule(String s){
       this.s = s;
    }
    protected void configure() {
      bind(DCE.class).toInstance(new DCEImpl(s));
    }
}

现在我有一个 class C,它需要一个 List<DCE> 和所有 3 个实现(实际上超过 3 个,使用 3 作为示例)。

我想在 C 中通过 Guice 注入这个列表。为此,我创建了一个新模块 DCEPModule,它将以这种方式提供 List<DCE>

@Provides
List<DCE> getDCE() {
      for(String s: S){
            Module m = new DCEModule(s);
            install(m);
            Injector injector = Guice.createInjector(m);
            listDomains.add(injector.getInstance(DCE.class));
        }
}

我的问题是我不想在这个模块中调用新的注入器,因为 DCEPModule 将由不同的模块安装。

public class NewModule extends AbstractModule {
   protected void configure() {
      install(DCEPModule);
    }

}

我想要一种无需在 DCEPModule 中显式创建新注入器即可获得 List<DCE> 的方法。

您可以使用 Multibinder (javadoc, wiki) 来实现。 这是一个例子:

public class SnacksModule extends AbstractModule {
    protected void configure(){
         Multibinder<Snack> multibinder = Multibinder.newSetBinder(binder(), Snack.class);
         multibinder.addBinding().toInstance(new Twix());
         multibinder.addBinding().toProvider(SnickersProvider.class);
         multibinder.addBinding().to(Skittles.class);
    }
}

现在,multibinder 将提供 Set<Snack>。如果你绝对需要一个 List 而不是 Set,那么你可以像这样向你的模块添加一个方法:

@Provides
public List<Snack> getSnackList(Set<Snack> snackSet) {
    return new ArrayList(snackSet);
}

您可以将实现添加到多个模块中的同一个多重绑定。当您调用 Multibinder.newSetBinder(binder, type) 时,它不一定会创建一个新的多重绑定。如果该类型的多绑定已经存在,那么您将获得现有的多绑定。