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

Дано

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 

, в этом проекте он должен запускаться

1 Ответ

0 голосов
/ 04 апреля 2019

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

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

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

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

  • (E1) развертывается в архиве bean-компонента, а
  • (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
...