CDI:2 个具有不同资格的生产者

CDI: 2 Producers with different qualifiers

我有 2 个生产者方法,一个只有 1 个限定符,一个有 2 个限定符,一个来自第一个生产者,另一个来自:

@ApplicationScoped
public class MyProducer {

  @Produces
  @Qualifier1
  MyBean produce1(InjectionPoint injectionPoint) {
    ...
  }

  @Produces
  @Qualifier1
  @Qualifier2
  MyBean produce2(InjectionPoint injectionPoint) {
    ...
  }
}

如果我尝试使用两个限定符 @Inject MyBean,一切正常,调用 produce2。但是当只用 @Qualifier1 注入 MyBean 时,我得到一个 AmbiguousResolutionException。在我看来,只有当注入点具有两个限定符时才应调用 produce2 。为什么不是这样,我该怎么做才能让它发挥作用?

不幸的是我无法更改生产者方法 1,因为它在库中。基本计划是,如果注入点有我的附加限定符,则调用我自己的生产者,如果没有,则调用库中的那个。

我认为观察到的行为已在 CDI 2.0 ch.2.3.4“指定注入字段的限定符”中明确指定:

A bean may only be injected to an injection point if it has all the qualifiers of the injection point.

假设一个注入点:

@Inject @Qualifier1 MyBean myBean;

然后produce1produce1生成的bean“具有注入点的所有限定符”,即@Qualifier1,所以两者都有资格在那里注射,导致 AmbiguousResolutionException.

事实上,规范给出的示例与 ch.2.3.6“重复限定符”中的问题完全相同。


那你能做什么?

首先,您真的需要用 @Qualifier1 来限定 produce2 吗?如果你没有充分的理由,只需从 produce2 中删除 @Qualifier1 即可完成 - 从库中使用 @Qualifier1 select MyBean 的注入点,使用 @Qualifier1 select MyBean 的注入点@Qualifier2 select 您的代码中的那个。 您的注入点不能同时具有 @Qualifier1@Qualifier2

如果您仍想将 MyBeanproduce2 注入到同时具有 @Qualifier1@Qualifier2 的注入点,你仍然可以这样做 [免责声明:还没有真正尝试过,它可能需要调整]。这有点复杂:您必须编写一个可移植的扩展,这根本不是一件难事。简要实施要点:

  • producer2 必须注释 ONLY with @Qualifier2
  • 在您的扩展中,观察 ProcessInjectionPoint 事件
  • 如果event.getInjectionPoint().getQualifiers()同时包含@Qualifier1@Qualifier2
    • 使用 event.configureInjectionPoint().qualifiers(...) 从限定符集中删除 @Qualifier1

效果是当 @Qualifier1 在运行时与 @Qualifier2 一起出现时,您将其删除。