使用Spring,您可以定义一个数组属性,并让Spring注入从给定类型派生的每个(@Component)类中的一个。
Guice中有相同的效果吗?或者是一个添加此行为的扩展点?
答案 0 :(得分:15)
这看起来像Guice MultiBinder的用例。你可能有类似的东西:
interface YourInterface {
...
}
class A implements YourInterface {
...
}
class B implements YourInterface {
...
}
class YourModule extends AbstractModule {
@Override protected void configure() {
Multibinder.newSetBinder(YourInterface.class).addBinding().to(A.class):
Multibinder.newSetBinder(YourInterface.class).addBinding().to(B.class):
}
}
你可以在任何地方注入Set<YourInterface>
:
class SomeClass {
@Inject public SomeClass(Set<YourInterface> allImplementations) {
...
}
}
这应该符合你的需要。
答案 1 :(得分:11)
Guice Multibindings要求您为A
&amp;显式添加绑定() B
到YourInterface
。如果你想要一个更透明的&#34; (自动)解决方案,例如AFAIK Spring开箱即用,然后假设Guice已经了解A
&amp; B
,因为您已经拥有A
&amp;的约束力无论如何,B
在其他地方,即使不明确但只是隐含的,例如通过其他地方的@Inject
,然后您可以使用此类内容进行自动发现(inspired by as done here,基于accessing Guice injector in a Module):
class YourModule extends AbstractModule {
@Override protected void configure() { }
@Provides
@Singleton
SomeClass getSomeClass(Injector injector) {
Set<YourInterface> allYourInterfaces = new HashSet<>();
for (Key<?> key : injector.getAllBindings().keySet()) {
if (YourInterface.class.isAssignableFrom(key.getTypeLiteral().getRawType())) {
YourInterface yourInterface = (YourInterface) injector.getInstance(key);
allYourInterfaces.add(yourInterface);
}
return new SomeClass(allYourInterfaces);
}
}
再次注意,此方法不需要任何类路径扫描;它只是查看Injector中所有IS-A YourInterface
的已知绑定。
答案 2 :(得分:1)
科特林
Class SomeModule : AbstractModule() {
override fun configure() {
val myBinder: Multibinder<MyInterface> = Multibinder.newSetBinder(binder(), MyInterface::class.java)
myBinder.addBinding().to(Implementation1::class.java)
myBinder.addBinding().to(Implementation2::class.java)
}
使用
@Inject constructor(private val someVar:Set<@JvmSuppressWildcards MyInterface>)