我如何处理继承类型的多种处置方法?

问题描述 投票:0回答:1

我有两节课。

class A {
}

class B extends A {
}

并且在我的生产者类中,我这样声明。

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

void disposeA(A a) {
    // empty
}

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

void disposeB(B b) {
    // empty
}

而且Weld抱怨。

....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)]

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

java cdi weld weld2 weld-junit5
1个回答
0
投票

这是一个类型安全的解析问题,它可以按预期工作。根据规范,3.4.3. Disposer method resolution

处置程序方法绑定到生产者方法或生产者字段,如果:

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

在您的特定情况下,您具有生产者方法produceB,该方法创建一个类型将为{B, A, Object}的bean。类型是从返回类型派生的,并将包含类型本身,所有超类和所有已实现的接口(as stated here in CDI spec)。

然后,您有两种处置方法,一种具有处置程序参数A,另一种具有B。您可以认为这些参数可以作为注入点,如果有帮助的话-您的produceB生产者方法会创建一个适合这两个处理程序的bean,因此会产生歧义,因为Weld对于每个bean最多需要一个处理程序方法。

如果要详细了解类型安全解析的工作原理,请查看here

关于如何“解决”这种情况,我可以从脑海中想出两种方法(可能有更多方法可以做到这一点:

  • 您可以在另一个bean中声明每个生产者+处理程序。根据规范,需要在生产者所在的同一个bean中声明处理程序,这样可以消除此问题。
  • 您可以使用@Typed on the producer并将@Typed的类型限制为仅produceB,这也可以解决这种情况,但是bean将不再适合注入任何类型为B.class的注入点。
© www.soinside.com 2019 - 2024. All rights reserved.