具有多个实现的Guice和接口

如果我有接口Validator和这个接口的多个实现。 如何使用Guice注入任何多个实现? 现在我知道我可以使用以下代码注入一个,但它只允许一个实现:

public class MyModule extends AbstractModule { @Override protected void configure() { bind(Validator.class).to(OneOfMyValidators.class); } } 

我想做的是:

 Validator v1 = injector.getInstance(Validator1.class); Validator v2 = injector.getInstance(Validator2.class); 

有可能吗?

简短回答:绑定注释。 它们基本上是一种让依赖者提供指向特定实例或实现的提示的方式,而不需要依赖于完整的具体实现类。

请参阅: https : //github.com/google/guice/wiki/BindingAnnotations

例如,在模块中,您可以执行以下操作:

 bind(Validator.class).annotatedWith(ValidatorOne.class).to(OneOfMyValidators.class); bind(Validator.class).annotatedWith(ValidatorTwo.class).to(SomeOtherValidator.class); 

在你的构造函数中,你会做:

 @Inject MyClass(@ValidatorOne Validator someValidator, @ValidatorTwo Validator otherValidator) { ... } 

要直接从Injector获取带注释的值,您必须使用Guice Key类,如:

 Validator v1 = injector.getInstance(Key.get(Validator.class, ValidatorOne.class)); 

另外,绑定注释对于注入运行时常量非常有用。 请参阅bindConstant的注释:

https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/Binder.html

在寻找将多个实现动态绑定到接口的解决方案时,我找到了这个线程,类似于Java中的ServiceLoader。 答案涵盖了更一般的情况,但它也可用于从集合中获取特定的实现。 Multibinder允许将多个实现绑定到一个类型:

 public class ValidatorsModule extends AbstractModule { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), Validator.class); multibinder.addBinding().toInstance(new ValidatorOne()); multibinder.addBinding().toInstance(new ValidatorTwo()); } } //Usage @Inject Set validators; 

与ejboy的提议非常相似,但由于您拥有不同的Validator类,因此您可以绑定到类本身,而不是手动创建实例。

 protected void configure() { ... Multibinder mb = Multibinder.newSetBinder(binder(), Validator.class); mb.addBinding().to(Validator1.class); mb.addBinding().to(Validator2.class); mb.addBinding().to(Validator3.class); ... } 

然后从使用的角度来看,例如通过构造函数注入:

 class UseCase { private Set allOfThem; @Inject public UseCase(Set allOfThem) { this.allOfThem = allOfThem; // eg iteratation for (Validator oneOfThem : allOfThem) { ... } } }