Почему производители не наследуются в 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 остается неудовлетворенным. Я знаю, что это согласуется с главой 4.2 CDI-Spec.

Чтобы это работало, мне нужно расширить SubClass на

 @Produces
 ProducedInSuperClass producedInSuperClassInSubClass = producedInSuperClass;

Кто-нибудь может объяснить это? Почему инъекции, перехватчики аннотаций ... наследуются, а не производители?

2
0
433
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Есть ли причина, по которой вы работаете только со статическими классами? Чтобы его можно было распознать, производитель должен быть размещен на реальном компоненте CDI. Ваш образец вырван из контекста, поэтому я не могу сказать, будут ли они действительно распознаны как бобы.

Однако при переносе вашего образца в нестатический тестовый пример (с некоторыми bean-компонентами @Vetoed и производителями для них) он будет работать так, как вы этого ожидаете - оба производителя будут найдены и произведут инъекционные bean-компоненты. Так что, возможно, вам нужно поделиться полным воспроизводимым образцом, и мы сможем продолжить.

Я подозреваю, что наследование, о котором вы спрашиваете, не является реальной проблемой здесь. Во всяком случае, он разработан так, поскольку CDI 1.0, поэтому найти обсуждение этого будет в лучшем случае проблематично (по крайней мере, без проблем с JIRA, я там проверял). Но сразу приходит в голову одна причина - предположить, что у производителей было наследование. Тогда в приведенном выше сценарии производитель ProducedInSuperClass будет в SuperClass, но из-за наследования также будет в SubClass. Предполагая, что оба являются допустимыми для внедрения (ни один из них не отключен через специализацию), вы теперь сталкиваетесь с неоднозначным исключением зависимости, поскольку у вас есть два производителя для одного и того же типа bean-компонента с одинаковыми квалификаторами bean-компонента, потому что SuperClass и SubClass - это два разных bean-компонента, и оба содержат производителя. Я бы сказал, что это справедливый повод для отключения наследования у производителей. Кроме того, по-прежнему с включенным наследованием вы можете переопределить метод в подклассе, и возникнет больше вопросов - вы сохраните оба или отключите исходный? Если вы сохраните их, каковы будут ограничения нового метода? Что, если вы выберете одно из них, а затем вы @Vetoed один из бобов?

С моей точки зрения, это просто дизайнерское решение. Вероятно, на месте, чтобы предотвратить дальнейшую путаницу. Хотя я знаю, что это не ответ, поэтому вы, вероятно, ищете, но сомнение в столь старых проектах редко дает более точные ответы :-)

Пример можно найти по адресу: github.com/1and1/ejb-cdi-unit/blob/rework-analyzing/…. Переопределение производителя: я сделал это, чтобы показать обходной путь ограничения невозможности наследования Produces. Что касается общей концепции переопределения: это сделано в других местах в спецификации, все хорошо. т.е. внедренные инициализаторы, PostConstruct, PreDestroy, поэтому концепция переопределения не должна быть проблемой.

aschoerk 05.11.2018 20:50
Ответ принят как подходящий

Why are ... inherited but not Producers?

Выдержка из JavaDoc из @Produces:

Producer methods and fields are not inherited by bean subclasses.

Если бы методы и поля производителя были унаследованы, тогда существовал бы несколько бобов ... подходящие для инъекции до точки инъекции, который CDI рассматривает как неоднозначная зависимость.

С другой стороны, CDI поддерживает специализация метода производителя:

@Mock
public class MockShop extends Shop {

   @Override @Specializes
   @Produces
   PaymentProcessor getPaymentProcessor() {
      return new MockPaymentProcessor();
   }

   @Override @Specializes
   @Produces
   List<Product> getProducts() {
      return PRODUCTS;
   }

   ...

}

Простое и разумное объяснение.

aschoerk 11.11.2018 11:20

Другие вопросы по теме