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 thi
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
.