With Spring, you can define an array property and have Spring inject one of every (@Component) class that derives from the given type.
Is there an equivalent for this in Guice? Or an extension point to add this behavior?
With Spring, you can define an array property and have Spring inject one of every (@Component) class that derives from the given type.
Is there an equivalent for this in Guice? Or an extension point to add this behavior?
This looks like a use case for Guice MultiBinder. You could have something like that:
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):
}
}
And you can inject a Set<YourInterface>
anywhere:
class SomeClass {
@Inject public SomeClass(Set<YourInterface> allImplementations) {
...
}
}
That should match with what you need.
Guice Multibindings require you to explicitly addBinding() for A
& B
to YourInterface
. If you would like a more "transparent" (automatic) solution such as what AFAIK Spring offers out-of-the-box, then assuming that Guice already knows about A
& B
because you already have a binding for A
& B
elsewhere anyway, even if not explicit but just implicit e.g. through an @Inject
somewhere else, then and only then you alternatively could use something like this for auto-discovery (inspired by as done here, based on 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);
}
}
Note again that this approach does NOT require any classpath scanning; it just looks at all already known bindings in the Injector for anything that IS-A YourInterface
.
Kotlin
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)
}
Usage
@Inject constructor(private val someVar:Set<@JvmSuppressWildcards MyInterface>)
© 2022 - 2024 — McMap. All rights reserved.