How to get all implementors/subclasses of an interface with Guice?

后端 未结 2 547
余生分开走
余生分开走 2020-12-10 11:34

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

相关标签:
2条回答
  • 2020-12-10 11:44

    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.

    0 讨论(0)
  • 2020-12-10 11:46

    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.

    0 讨论(0)
提交回复
热议问题