【发布时间】:2011-05-22 00:03:39
【问题描述】:
使用 Spring,您可以定义一个数组属性并让 Spring 注入从给定类型派生的每个 (@Component) 类。
Guice 中是否有类似的功能?还是添加此行为的扩展点?
【问题讨论】:
使用 Spring,您可以定义一个数组属性并让 Spring 注入从给定类型派生的每个 (@Component) 类。
Guice 中是否有类似的功能?还是添加此行为的扩展点?
【问题讨论】:
这看起来像是 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) {
...
}
}
这应该与您的需要相匹配。
【讨论】:
Guice Multibindings 要求您将A 和B 的显式addBinding() 添加到YourInterface。如果您想要一个更“透明”(自动)的解决方案,例如 AFAIK Spring 提供的开箱即用的解决方案,那么假设 Guice 已经知道 A 和 B,因为您已经有了 @987654330 的绑定@ & 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);
}
}
再次注意,这种方法不需要任何类路径扫描;它只是查看注入器中所有已知的绑定,以查找任何 IS-A YourInterface。
【讨论】:
科特林
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>)
【讨论】: