【问题标题】:Why are Producers not inherited in CDI为什么 CDI 中不继承生产者
【发布时间】:2018-10-31 11:18:55
【问题描述】:

给定以下类

    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 章是一致的,我知道。

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

扩展子类
 @Produces
 ProducedInSuperClass producedInSuperClassInSubClass = producedInSuperClass;

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

【问题讨论】:

    标签: java inversion-of-control cdi weld


    【解决方案1】:

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

    摘自JavaDoc of @Produces

    生产者方法和字段不被 bean 子类继承。

    如果生产者方法和字段将被继承,那么将存在 多个 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;
       }
    
       ...
    
    }
    

    【讨论】:

    • 简单合理的解释。
    【解决方案2】:

    你有什么理由只对静态类进行操作吗? Producer 需要放置在实际的 CDI bean 上才能被识别。您的示例与上下文无关,因此我不能说它们是否真的会被识别为 bean。

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

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

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

    【讨论】:

    • 可以在以下位置找到示例:github.com/1and1/ejb-cdi-unit/blob/rework-analyzing/…。覆盖生产者:我这样做是为了展示一种解决方法,以解决无法继承 Produces 的限制。关于覆盖的一般概念:在规范中的其他地方做得很好。即注入的初始化程序、PostConstruct、PreDestroy,因此覆盖概念应该不是问题。
    猜你喜欢
    • 2013-06-16
    • 2023-03-29
    • 2015-04-08
    • 1970-01-01
    • 2022-10-12
    • 1970-01-01
    • 2013-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多