@替代和默认实施CDI

问题描述

@Inject
Instance<FooInterface> fooInstances;

DefaultImplementation implements FooInterface{}

@Alternative
@Priority(1)
AlternativeImplementation implements FooInterface{}

尽管实例仅具有AlternativeImplementation而不具有DefaultImplementation,但仍要遍历并返回请求的fooImplementation作为参数。

解决此问题的解决方案是什么?我真的需要两种实现方式。

public FooInterface getImplementation(String name){
   Iterator<FooInterface> iterator = fooInstances.iterator();
    while (iterator.hasNext()) {
          FooInterface fooInterface = iterator.next();
         if (fooInterface .getName().equals(strategyName)) {
              return fooInterface ;
         }
    }
}

解决方法

根据CDI Specification

5.1.2。启用和禁用的豆子

如果满足以下条件,则可以说启用了

  • 将其部署在Bean归档文件中,并且
  • 它不是禁用bean的生产者方法或字段,并且
  • 它不受“专用化”中定义的任何其他启用的Bean专用,并且
  • 这不是替代方案,或者它是至少一个Bean归档文件或应用程序的选定替代方案

否则,该bean被称为已禁用

在您的情况下,DefaultImplementation是禁用的bean,因为由于存在AlternativeImplementation注释而选择了备用@Priority bean。


继续执行以下操作:

  1. 从所有实现@Alternative的类中删除FooInterface注释

  2. 引入一个qualifier以选择首选实例:

    @Qualifier
    @Retention(RUNTIME)
    @Target({METHOD,FIELD,PARAMETER,TYPE})
    public @interface Preferred {
    }
    
  3. 使用该限定符注释DefaultImplementation

    @Preferred
    DefaultImplementation implements FooInterface{}
    
  4. 使用以下注入点声明来访问实现该接口的所有bean:

    @Inject
    @Any
    Instance<FooInterface> fooInstances;
    

    尽管如此,您仍需要在代码中显式处理@Priority

  5. 使用以下注入点声明来获取首选的bean:

    @Inject
    @Preferred
    FooInterface preferredFooInstance;
    
,

这就是@Any限定词的作用。所有bean都具有@Any限定符,除非有人竭尽全力将其省略。

@Inject
@Any
Instance<FooInterface> fooInstances;

请注意,您现在必须自己应用相关的替代和优先级与默认实例逻辑。您可能会追求别的东西,但严格来说,这是您问题的答案。