Weld CDI: производители суперклассов альтернатив эффективны, несмотря на cdi-spec

Дано

public class BeanContainer {
   @Produces
   Bean bean = new Bean();
}

и его альтернатива:

@Alternative
public class BeanContainerAlt extends BeanContainer {
    @Produces
    int producerInt = 10;
}

где боб

public class Bean {
    boolean didPostConstruct = false;
    @PostConstruct
    public void postConstruct() {
        didPostConstruct = true;
    }
}

введено в MainClass:

public class MainClass {
    @Inject
    Bean bean;
    @Inject
    Integer producedInt;
}

Затем:

  Weld weld = new Weld()
            .disableDiscovery()
            .addBeanClass(MainClass.class)
            .addBeanClass(BeanContainer.class)
            .addBeanClass(BeanContainerAlt.class)
            .alternatives(BeanContainerAlt.class);
    WeldContainer container = weld.initialize();
    final MainClass mainClass = container.select(MainClass.class).get();
    assertFalse(mainClass.bean.didPostConstruct);
    assertEquals(10, (long)mainClass.producedInt);
    BeanContainer containerObject = container.select(BeanContainer.class).get();
    assertEquals(BeanContainerAlt.class, containerObject.getClass());

не дает ошибок. Я ожидал, что Bean.class должен быть добавлен с использованием addBeanClass, чтобы можно было выполнить инъекцию в MainClass. Объяснение состоит в том, что Суперкласс BeanContainerAlt, чьи Производители должны быть неэффективными, создает Боб-объект. Предназначено ли это поведение или даже в соответствии со спецификацией (я не нашел его), возможно, оно определено в документации по сварке?

Исходный код можно найти в examplesrc

mvn clean install -Dtest=ReproProducersInSuperclasses 

в этом проекте должен заставить его работать

0 ответов

Действительно, поля и методы помечены @Producer не наследуются - как обсуждалось в принятом ответе на вопрос, почему производители не наследуются в CDI

Однако согласно спецификации CDI:

5.1.2. Включенные и отключенные бины

Бин считается включенным, если:

  • (E1) он развернут в архиве компонентов и
  • (E2) это не метод производителя или поле отключенного компонента, и
  • (E3) он не специализирован никаким другим включенным компонентом, как определено в Специализации, и либо
  • (E4) это не альтернатива, или это выбранная альтернатива, по крайней мере, одного архива бина или приложения.

В противном случае бин считается отключенным.

В соответствии с этими определениями и кодом выше:

  • BeanContainer не является альтернативой (E4) и, следовательно, включен управляемый компонент
  • BeanContainerAlt является выбранной альтернативой (E4) и, следовательно, включен управляемый компонент
  • Bean а также int включены, потому что они не являются методом производителя или полем отключенного компонента (E2), так как BeanContainer а также BeanContainerAlt оба включены (E4)

Поэтому поля производителя в обоих BeanContainer а также BeanContainerAlt используются для разрешения зависимостей.


Тест не проходит, как показано ниже, когда BeanContainer не развернут (E1):

WELD-001408: Unsatisfied dependencies for type Bean with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject
net.oneandone.iocunit.testalt.MainClass.bean

Тест не проходит, как показано ниже, когда BeanContainerAlt не выбран (E4):

WELD-001408: Unsatisfied dependencies for type Integer with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject
net.oneandone.iocunit.testalt.MainClass.producedInt
Другие вопросы по тегам