为什么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 限定符,因为 SuperClass
和 SubClass
是两个不同的 bean,都包含一个生产者。
我会说这是禁用生产者继承的合理理由。此外,仍然在继承的情况下,您可以覆盖子类中的方法,并且会出现更多问题 - 您是保留两者还是禁用原始方法?如果保留它们,新方法的局限性是什么?如果您决定选择其中一个然后 @Vetoed
其中一个豆子怎么办?
在我看来,这只是一个设计决定。可能是为了防止进一步混淆。虽然我知道这不是答案,所以您可能正在寻找,质疑如此陈旧的设计很少能得到更准确的答案:-)
Why are ... inherited but not Producers?
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;
}
...
}
鉴于以下 类
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 限定符,因为 SuperClass
和 SubClass
是两个不同的 bean,都包含一个生产者。
我会说这是禁用生产者继承的合理理由。此外,仍然在继承的情况下,您可以覆盖子类中的方法,并且会出现更多问题 - 您是保留两者还是禁用原始方法?如果保留它们,新方法的局限性是什么?如果您决定选择其中一个然后 @Vetoed
其中一个豆子怎么办?
在我看来,这只是一个设计决定。可能是为了防止进一步混淆。虽然我知道这不是答案,所以您可能正在寻找,质疑如此陈旧的设计很少能得到更准确的答案:-)
Why are ... inherited but not Producers?
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;
}
...
}