如何使用Guice获得接口的所有实现者/子类?

时间:2022-09-25 10:58:43

With Spring, you can define an array property and have Spring inject one of every (@Component) class that derives from the given type.

使用Spring,您可以定义一个数组属性,并让Spring注入来自给定类型的每个(@Component)类中的一个。

Is there an equivalent for this in Guice? Or an extension point to add this behavior?

在Guice有类似的东西吗?或者添加这个行为的扩展点?

2 个解决方案

#1


12  

This looks like a use case for Guice MultiBinder. You could have something like that:

这看起来像是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):
    }
}

And you can inject a Set<YourInterface> anywhere:

你可以在任何地方插入一个集合 <你的接口> :

class SomeClass {
    @Inject public SomeClass(Set<YourInterface> allImplementations) {
        ...
    }
}

That should match with what you need.

那应该和你需要的相符。

#2


7  

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):

Guice多绑定要求您将A和B显式地添加到接口中。如果你想更“透明”(自动)解决方案,如春季AFAIK提供开箱即用的,那么假设Guice已经知道a和B为a和B,因为你已经有一个绑定其他地方无论如何,即使没有明确的只是隐如通过@ inject别的地方,然后,只有你或者可以使用这样的自动发现(灵感来自这里,基于访问Guice注入器模块):

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.

再次注意,这种方法不需要任何类路径扫描;它只会检查注入器中所有已知的绑定——你的接口。

#1


12  

This looks like a use case for Guice MultiBinder. You could have something like that:

这看起来像是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):
    }
}

And you can inject a Set<YourInterface> anywhere:

你可以在任何地方插入一个集合 <你的接口> :

class SomeClass {
    @Inject public SomeClass(Set<YourInterface> allImplementations) {
        ...
    }
}

That should match with what you need.

那应该和你需要的相符。

#2


7  

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):

Guice多绑定要求您将A和B显式地添加到接口中。如果你想更“透明”(自动)解决方案,如春季AFAIK提供开箱即用的,那么假设Guice已经知道a和B为a和B,因为你已经有一个绑定其他地方无论如何,即使没有明确的只是隐如通过@ inject别的地方,然后,只有你或者可以使用这样的自动发现(灵感来自这里,基于访问Guice注入器模块):

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.

再次注意,这种方法不需要任何类路径扫描;它只会检查注入器中所有已知的绑定——你的接口。