Как я могу обрабатывать несколько методов удаления для унаследованных типов?
У меня два класса.
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)]
Это нормально? Как я могу это решить?
1 ответ
Это вопрос безопасного разрешения, и он работает по назначению. Из спецификации, 3.4.3. Разрешение метода диспоузера:
Метод распределения привязан к методу производителя или полю производителя, если:
- метод производителя или поле производителя объявляется тем же классом bean-компонента, что и метод disposer, и
- метод производителя или поле производителя назначается удаленному параметру в соответствии с правилами разрешения типов, определенными в разрешении типов (с использованием возможности присвоения исходных и параметризованных типов).
В вашем конкретном случае у вас есть метод производителя produceB
который создает bean-компонент, типы которого будут {B, A, Object}
. Типы являются производными от возвращаемого типа и будут содержать сам тип, все суперклассы и все реализованные интерфейсы (как указано здесь в спецификации CDI).
Затем у вас есть два метода удаления, один с параметром средства удаления. A
, другой с B
. Вы можете думать об этих параметрах как о точках введения, если это помогает - вашproduceB
Метод производителя создает компонент, который подходит для обоих этих устройств распределения, что создает неоднозначность, поскольку Weld требуется не более одного метода удаления для каждого компонента.
Если вы хотите узнать больше о том, как именно работает типизированное разрешение, посмотрите здесь.
Что касается того, как "разрешить" эту ситуацию, я могу придумать два подхода из головы (вероятно, есть другие способы сделать это):
- Вы можете объявить каждый производитель + распределитель в другом компоненте. Согласно спецификации, disposer должен быть объявлен в том же bean-компоненте, где находится производитель, чтобы устранить эту проблему.
- Вы можете использовать
@Typed
на производителя и ограничить типыproduceB
толькоB.class
что должно разрешить и эту ситуацию, но компонент больше не будет иметь право на инъекцию в любую точку инъекции с типомA
.