为什么生产者未在CDI中继承

时间:2018-10-31 11:18:55

标签: java inversion-of-control cdi weld

提供以下课程

    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规范第4.2章是一致的。

要执行此操作,我需要通过

扩展SubClass。
 @Produces
 ProducedInSuperClass producedInSuperClassInSubClass = producedInSuperClass;

有人可以对此进行解释吗?为什么“注入,注释拦截器...”是继承的,而不是“生产者”?

2 个答案:

答案 0 :(得分:5)

有什么理由只对静态类进行操作?生产者需要放置在要识别的实际CDI bean上。您的样本已脱离上下文,因此我无法确定它们是否将被实际识别为bean。

但是,将您的样本转移到非静态测试用例(有一些@Vetoed豆并为其生产者),它将按照您的预期运行-将找到两个生产者并生产可注射的豆。因此,也许您需要共享完整的可重现样品,我们可以从那里开始。

我怀疑您要问的继承不是这里的实际问题。 无论如何,从CDI 1.0开始就这样设计,因此最好就此进行讨论很麻烦(至少没有JIRA问题,我确实检查过那里)。 但是立即想到的一个原因-假定继承对于生产者来说已经存在。这样,您的上述情况在ProducedInSuperClass中将有一个SuperClass的生产者,但由于在SubClass中也将继承。假设两者都是合法的注入对象(没有通过专门化禁用),那么您现在面临一个模棱两可的依赖异常,因为您有两个具有相同bean限定符的相同bean类型的生产者,因为SuperClassSubClass是两个不同的豆并且都包含一个生产者。 我要说的是在生产者上禁用继承的合理原因。此外,仍然保持继承状态,然后可以重写子类中的方法,并出现更多问题-是否同时保留这两个方法?如果保留它们,新方法的局限性是什么?如果您决定选择其中一个,然后@Vetoed一个豆,该怎么办?

在我看来,这只是设计决定。可能到位以防止进一步的混乱。虽然我知道这不是答案,所以您可能正在寻找,但质疑如此古老的设计很少会提供更准确的答案:-)

答案 1 :(得分:3)

  

为什么...是继承人,而不是生产者?

摘录自JavaDoc of @Produces

  

生产者方法和字段不被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;
   }

   ...

}