如何通过 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)
时,它不一定会创建一个新的多重绑定。如果该类型的多绑定已经存在,那么您将获得现有的多绑定。
有一个接口 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)
时,它不一定会创建一个新的多重绑定。如果该类型的多绑定已经存在,那么您将获得现有的多绑定。