CDI PostConstruct с использованием поставщика услуг

Я пытаюсь создать приложение с использованием Java EE 6. Разработка ведется на TomEE 1.7. По разным причинам мне приходится создавать большинство моих управляемых объектов CDI через поставщика услуг. Однако, когда я это делаю, аннотированный метод @PostConstruct созданного компонента не вызывается. Если я уберу поставщика услуг и позволю CDI создать объект непосредственно через его конструктор, он будет вызван. Это нормально или это ошибка поставщика CDI, с которым поставляется TomEE (Open WebBeans)

Спасибо


person Mihai Tudor    schedule 17.10.2014    source источник


Ответы (2)


Это нормальное поведение. Метод @PostConstruct вызывается, когда bean-компонент инициализируется контейнером. См. Справочник по сварке:

Немного упрощая, все происходит в таком порядке:

  • Сначала контейнер вызывает конструктор компонента (конструктор по умолчанию или конструктор с аннотацией @Inject), чтобы получить экземпляр
    компонента.

  • Далее контейнер инициализирует значения всех введенных полей бина.

  • Далее контейнер вызывает все методы инициализации бина (порядок вызова не переносимый, не полагайтесь на него).
  • Наконец, вызывается метод @PostConstruct, если он есть.

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

person Gas    schedule 17.10.2014
comment
Я заставил его работать, вызвав метод @PostConstruct непосредственно в производителе. Я пробовал это раньше, но не смог этого сделать, потому что метод зависел от других компонентов, введенных в созданный. Выяснив, что методы-производители используют свои аргументы, заполнили пробел. - person Mihai Tudor; 20.10.2014

Кажется плохой практикой использовать производителя для всего — почему вы используете производителя, если ваши классы аннотированы @PostConstruct?

Один из способов сделать это — использовать создающий контекст внутри вашего метода производителя, чтобы предоставить ссылку, а затем вызвать пост-конструкцию для этой ссылки. Вот пример кода, взятый из Apache DeltaSpike, набора расширений CDI:

BeanProvider

    BeanManager beanManager = getBeanManager();

    CreationalContext creationalContext = beanManager.createCreationalContext(null);

    AnnotatedType annotatedType = beanManager.createAnnotatedType(instance.getClass());
    InjectionTarget injectionTarget = beanManager.createInjectionTarget(annotatedType);
    injectionTarget.inject(instance, creationalContext);
    injectionTarget.postConstruct(instance);
person John Ament    schedule 18.10.2014
comment
Я использую производителя, потому что большинство компонентов, которые внедряются в UI-бины, бывают двух видов, и то, что создается, определяется параметрами времени выполнения. Ваш пример кода, кажется, связывает пост-конструкцию внедренного bean-компонента с точкой инъекции, поэтому для нескольких точек инъекции мне нужно будет сделать некоторое управление тем, какая точка инъекции вызывает пост-конструкцию. - person Mihai Tudor; 20.10.2014
comment
Я не уверен, что ты имеешь в виду. Что заставляет вас так думать? Это содержимое метода производителя, например, после того, как вы создали свой экземпляр. InjectionTarget — это просто API в CDI, который позволяет вам вызывать методы PostConstruct или PreDestroy для управляемого объекта. - person John Ament; 20.10.2014
comment
Извините, моя интерпретация была просто догадкой. Я предположил, что InjectionTarget представляет bean-компонент, в который внедряется созданный экземпляр, и что код запускается, когда происходит внедрение. Виноват. Когда у меня будет немного времени, я повнимательнее рассмотрю DeltaSpike, это кажется стоящей инвестицией. - person Mihai Tudor; 22.10.2014