为什么CDI不继承Producers

Why are Producers not inherited in CDI

鉴于以下 类

    private static class ProducedInSubClass {
    }

    private static class ProducedInSuperClass {
    }

    public static class SuperClass {    
        @Produces
        public ProducedInSuperClass producedInSuperClass = new ProducedInSuperClass();
    }

    public static class SubClass extends SuperClass {
        @Produces
        ProducedInSubClass producedInSubClass = new ProducedInSubClass();
    }

   public static class BeanWithSubClass {          
        @Inject
        SubClass subClass;
        @Inject
        ProducedInSuperClass producedInSuperClass;
        @Inject
        ProducedInSubClass producedInSubClass;
   }

ProducedInSuperClass 的注入未得到满足。我知道这与 CDI-Spec 第 4.2 章一致。

为了完成这项工作,我需要通过

扩展 SubClass
 @Produces
 ProducedInSuperClass producedInSuperClassInSubClass = producedInSuperClass;

谁能解释一下?为什么 Injects、Annotations Interceptors... 是继承的而不是 Producers?

为什么你只对静态 类 进行操作?生产者需要放置在实际的 CDI bean 上才能被识别。您的样本脱离了上下文,所以我不能说它们是否真的会被识别为 beans。

但是,将您的样本转移到非静态测试用例(带有一些@Vetoed bean 和它们的生产者),它将 运行 正如您所期望的那样 - 两个生产者都会被发现并生产可注射的豆子。所以也许您需要分享一个完整的可重现样本,我们可以从那里开始。

我怀疑你问的继承不是这里的实际问题。 无论如何,自 CDI 1.0 以来它就是这样设计的,所以找到关于它的讨论充其量也很麻烦(至少没有 JIRA 问题,我在那里检查过)。 但是马上想到一个原因——假设生产者继承。那么你的上述场景将在 SuperClass 中有一个 ProducedInSuperClass 的生产者,但由于继承也在 SubClass 中。假设两者都是合法的注入(none 通过专门化禁用),那么您现在面临一个不明确的依赖异常,因为您有两个生产者使用相同的 bean 类型和相同的 bean 限定符,因为 SuperClassSubClass 是两个不同的 bean,都包含一个生产者。 我会说这是禁用生产者继承的合理理由。此外,仍然在继承的情况下,您可以覆盖子类中的方法,并且会出现更多问题 - 您是保留两者还是禁用原始方法?如果保留它们,新方法的局限性是什么?如果您决定选择其中一个然后 @Vetoed 其中一个豆子怎么办?

在我看来,这只是一个设计决定。可能是为了防止进一步混淆。虽然我知道这不是答案,所以您可能正在寻找,质疑如此陈旧的设计很少能得到更准确的答案:-)

Why are ... inherited but not Producers?

摘自JavaDoc of @Produces

Producer methods and fields are not inherited by bean subclasses.

如果生产者方法和字段将被继承,那么将存在 多个 bean ... 有资格注入到注入点 ,CDI 将其视为 ambiguous dependency

另一方面,CDI支持producer method specialization:

@Mock
public class MockShop extends Shop {

   @Override @Specializes
   @Produces
   PaymentProcessor getPaymentProcessor() {
      return new MockPaymentProcessor();
   }

   @Override @Specializes
   @Produces
   List<Product> getProducts() {
      return PRODUCTS;
   }

   ...

}