0

我有两节课。

class A {
}

class B extends A {
}

在我的制片人课上,我是这样声明的。

@Produces A produceA(InjectionPoint ip) {
    return new A();
}

void disposeA(@Disposes A a) {
    // empty
}

@Produces B produceB(InjectionPoint ip) {
    return new B();
}

void disposeB(@Disposes B b) {
    // empty
}

韦尔德抱怨道。

....DefinitionException: WELD-000077: Cannot declare multiple disposal methods for this producer method.

Producer method:  org.jboss.weld.bootstrap.BeanDeployer@41e68d87
Disposal methods:  
  - Disposer method [[BackedAnnotatedMethod] ....Producer.disposeA(@Disposes A)],
  - Disposer method [[BackedAnnotatedMethod] ....Producer.disposeB(@Disposes B)]

这是正常的吗?我该如何解决?

4

1 回答 1

4

这是一个类型安全的解决方案,它按预期工作。从规范,3.4.3。Disposer 方法解析

在以下情况下,处置器方法绑定到生产者方法或生产者字段:

  • producer 方法或 producer 字段由与 disposer 方法相同的 bean 类声明,并且
  • 根据类型安全解析中定义的类型安全解析规则(使用原始和参数化类型的可分配性),生产者方法或生产者字段可分配给已处置的参数。

在您的特定情况下,您有 producer 方法,该方法produceB创建一个 bean,其类型将是{B, A, Object}. 类型派生自返回类型,并将包含类型本身、所有超类和所有实现的接口(如 CDI 规范中所述)。

然后,您有两种 disposer 方法,一种带有 disposer 参数A,另一种带有B. 如果有帮助,您可以将这些参数视为注入点 - 您的produceB生产者方法创建一个适合这两个处理器的 bean,因此会产生歧义,因为 Weld 最多需要一个处理器方法用于每个 bean。

如果您想详细了解类型安全解析的工作原理,请查看此处

至于如何“解决”这种情况,我可以想到两种方法(可能有更多方法可以做到这一点):

  • 您可以在另一个 bean 中声明每个生产者 + 处置者。根据规范,处理程序需要在生产者所在的同一 bean 中声明,这样可以消除这个问题。
  • 您可以@Typed在生产者上使用并将类型限制produceB为仅B.class应该解决这种情况的类型,但是 bean 将不再有资格注入到任何类型为 的注入点A
于 2019-10-30T08:46:01.060 回答