具有多个实现的 Guice 和接口

2022-09-02 19:53:01

如果我有接口验证器和此接口的多个实现。如何用 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);

有可能吗?


答案 1

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

请参见: 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) {
  ...
}

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

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


答案 2

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

public class ValidatorsModule extends AbstractModule {
  protected void configure() {
      Multibinder<Validator> multibinder
          = Multibinder.newSetBinder(binder(), Validator.class);
      multibinder.addBinding().toInstance(new ValidatorOne());
      multibinder.addBinding().toInstance(new ValidatorTwo());
  }
}

//Usage
@Inject Set<Validator> validators;

推荐