it-swarm.com.ru

Java EE 6 @ javax.annotation.ManagedBean против @ javax.inject.Named vs. @ javax.faces.ManagedBean

Я чувствую, что в спецификации Java EE 6 есть небольшой беспорядок. Есть несколько наборов аннотаций.

У нас есть javax.ejb аннотации, такие как @Stateful и @Stateless для создания EJB.

Существует также @javax.annotation.ManagedBean для создания управляемого компонента.

В javax.enterprise.context есть аннотации, такие как @SessionScoped и @RequestScoped.

Более того, есть также аннотации @ManagedBean и @SessionScoped/@RequestScoped в пакете javax.faces.bean.

А для усложнения событий есть пакет javax.inject с аннотацией @Named.

Может кто-нибудь, пожалуйста, опишите, как они связаны друг с другом?

Где я могу использовать @EJB, @Inject или @ManagedPropery для инъекции других бинов?

104
Piotr Gwiazda

Прежде всего позвольте мне сделать некоторые разъяснения:

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

В Javaee у нас есть много контейнеров, которые управляют жизненным циклом своих объектов, таких как контейнер JSF, контейнер EJB, контейнер CDI, контейнер сервлетов и т.д.

Все эти контейнеры работают независимо друг от друга, они загружаются при инициализации сервера приложений и сканируют классы всех артефактов, включая файлы jar, ejb-jar, war и ear, во время развертывания, собирают и хранят некоторые метаданные о них, а затем, когда вам нужен объект класса во время выполнения они дадут вам экземпляры этих классов, а после завершения работы они уничтожат их.

Итак, мы можем сказать, что имеем:

  • JSF управляемые бобы
  • CDI управляемые бобы
  • EJB управляемые бобы
  • И даже сервлеты являются управляемыми bean-компонентами, потому что они создаются и уничтожаются контейнером, который является контейнером сервлета.

Поэтому, когда вы видите слово "Управляемый компонент", вам следует спросить о его контексте или типе (JSF, CDI, EJB и т.д.).

Тогда вы можете спросить, почему у нас много таких контейнеров: AFAIK, Java EE хотели создать среду внедрения зависимостей, но они не смогли собрать все требования в одной спецификации, потому что не могли предсказать будущие требования и они создали EJB 1.0, а затем 2.0, а затем 3.0 и теперь 3.1, но целью EJB были лишь некоторые требования (транзакция, модель распределенных компонентов и т. д.).

В то же время (параллельно) они поняли, что им тоже нужно поддерживать JSF, затем они создали управляемые JSF-компоненты и еще один контейнер для JSF-бинов и посчитали его зрелым DI-контейнером, но все же он не был полным и зрелым контейнером.

После этого Гэвин Кинг и некоторые другие ребята из Nice сделали CDI, самый зрелый контейнер DI, который я когда-либо видел. CDI (вдохновленный Seam2, Guice и Spring) был создан, чтобы заполнить пробел между JSF и EJB и множеством других полезных вещей, таких как инъекция pojo, методы продюсеров, перехватчики, декораторы, интеграционный SPI, очень гибкий и т.д., И он может даже сделать что делают управляемые EJB и JSF бины, тогда у нас может быть только один зрелый и мощный DI-контейнер. Но по какой-то обратной совместимости и по политическим причинам Java EE парни хотят сохранить их !!!

Здесь вы можете найти разницу и варианты использования для каждого из этих типов:

Управляемые компоненты JSF, компоненты CDI и EJB

JSF изначально разрабатывался с собственным механизмом управления управляемыми компонентами и компонентами, который был улучшен для JSF 2.0 и теперь включает компоненты на основе аннотаций. Когда CDI был выпущен вместе с Java EE 6, он рассматривался как структура управляемых компонентов для этой платформы, и, конечно, EJB-системы устарели, поскольку все они существовали уже более десяти лет.

Проблема, конечно, в том, чтобы знать, какой использовать и когда их использовать.

Давайте начнем с самых простых, управляемых JSF bean-компонентов.

JSF Managed Beans

Короче говоря, не используйте их, если вы разрабатываете для Java EE 6 и используете CDI. Они предоставляют простой механизм для внедрения зависимостей и определения базовых компонентов для веб-страниц, но они гораздо менее мощны, чем компоненты CDI.

Их можно определить с помощью аннотации @javax.faces.bean.ManagedBean, которая принимает необязательный параметр name. Это имя может использоваться для ссылки на bean-компонент со страниц JSF.

Область может быть применена к компоненту с использованием одной из различных областей, определенных в пакете javax.faces.bean, которые включают в себя запрос, сеанс, приложение, представление и пользовательские области.

@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
    ....
    ....
}

Бины JSF нельзя смешивать с другими видами бинов без какого-либо ручного кодирования.

CDI Beans

CDI - это структура управления bean-компонентами и внедрения зависимостей, выпущенная как часть Java EE 6 и включающая в себя комплексное комплексное средство управляемых bean-компонентов. Компоненты CDI намного более продвинуты и гибки, чем простые управляемые компоненты JSF. Они могут использовать перехватчики, область разговора, события, безопасное внедрение типа, декораторы, стереотипы и методы производителя.

Для развертывания компонентов CDI необходимо поместить файл с именем beans.xml в папку META-INF на пути к классам. Как только вы это сделаете, каждый компонент в пакете становится компонентом CDI. В CDI есть много функций, их слишком много, чтобы их можно было здесь описать, но в качестве краткого справочника по функциям, подобным JSF, вы можете определить область действия компонента CDI, используя одну из областей, определенных в пакете javax.enterprise.context (а именно, request, области разговоров, сеансов и приложений). Если вы хотите использовать компонент CDI со страницы JSF, вы можете дать ему имя, используя аннотацию javax.inject.Named. Чтобы добавить bean-компонент в другой bean-компонент, необходимо аннотировать поле аннотацией javax.inject.Inject.

@Named("someBean")
@RequestScoped
public class SomeBean {

    @Inject
    private SomeService someService;
}

Автоматическая инъекция, подобная определенной выше, может контролироваться с помощью квалификаторов, которые могут помочь сопоставить определенный класс, который вы хотите внедрить. Если у вас есть несколько типов платежей, вы можете добавить спецификатор для того, является ли он асинхронным или нет. Хотя вы можете использовать аннотацию @Named в качестве квалификатора, вы не должны использовать ее для демонстрации компонентов в EL.

CDI обрабатывает инъекцию бобов с несовпадающими областями действия с помощью прокси. Из-за этого вы можете внедрить bean-объект области действия запроса в bean-объект области действия, и ссылка будет по-прежнему действительна для каждого запроса, поскольку для каждого запроса прокси-сервер повторно подключается к действующему экземпляру bean-объекта области действия.

CDI также имеет поддержку перехватчиков, событий, новой области диалога и многих других функций, что делает его намного лучшим выбором по сравнению с управляемыми компонентами JSF.

EJB

EJB предшествуют bean-компонентам CDI и в некотором роде похожи на bean-компоненты CDI, а в других отношениях сильно отличаются. Прежде всего, различия между компонентами CDI и EJB заключаются в том, что EJB:

  • Транзакционный
  • Удаленный или локальный
  • Способен пассивировать бины с сохранением состояния, освобождая ресурсы
  • Возможность использовать таймеры
  • Может быть асинхронным

Два типа EJB называются без сохранения состояния и с состоянием. EJB без сохранения состояния можно рассматривать как поточно-ориентированные одноразовые компоненты, которые не поддерживают никакого состояния между двумя веб-запросами. EJB с состоянием действительно поддерживают состояние и могут быть созданы и сидеть без дела столько времени, сколько они необходимы, пока они не будут уничтожены.

Определить EJB просто, вы просто добавляете аннотацию javax.ejb.Stateless или javax.ejb.Stateful к классу.

@Stateless
public class BookingService {

  public String makeReservation(Item Item, Customer customer) {
    ...
    ...
  }
}

Бины без состояния должны иметь зависимую область, в то время как бин с состоянием может иметь любую область. По умолчанию они являются транзакционными, но вы можете использовать аннотацию атрибута транзакции.

Хотя EJB-компоненты и компоненты CDI сильно различаются по функциям, написание кода для их интеграции очень похоже, поскольку компоненты EJB можно вводить в EJB-компоненты, а объекты EJB можно вставлять в компоненты EJB. Нет необходимости делать какие-либо различия при введении одного в другой. Опять же, различные области действия обрабатываются CDI с использованием прокси. Единственным исключением является то, что CDI не поддерживает внедрение удаленных EJB-компонентов, но это можно реализовать, написав для него простой метод-производитель.

Аннотация javax.inject.Named, а также любые квалификаторы могут использоваться в EJB для сопоставления его с точкой внедрения.

Когда использовать какой бин

Как вы знаете, когда использовать какой боб? Просто.

Никогда не используйте управляемые компоненты JSF, если вы не работаете в контейнере сервлетов и не хотите пытаться заставить CDI работать в Tomcat (хотя для этого есть несколько архетипов Maven, поэтому нет никаких оправданий).

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

Если вам нужно использовать @ViewScoped в CDI, вам следует

  • используйте модуль seam-face или CODI MyFaces . просто добавьте один из них в ваш classpath, и @ViewScoped будет работать в CDI. MyFaces CODI имеет еще более надежную поддержку @ViewScoped
  • используйте MyFaces CODI @ViewAccessScoped, это расширение, написанное поверх CDI Apache, просто скачать его и использовать аннотацию @ViewAccessScoped вместо @ViewScoped.
  • Используйте CDI @ConversationScoped и сделайте его долгим. Смотрите здесь для получения дополнительной информации .
  • Используйте Omnifaces @ViewScoped аннотация

Некоторые части украдены у здесь .

189
Heidarzadeh

Да, это может сбивать с толку.

По некоторым ehm историческим причинам JSF и CDI используют одни и те же аннотации для областей, но из разных пакетов.

Как вы, вероятно, догадались, они из javax.faces.bean взяты из спецификации JSF и не связаны с CDI. Не используйте их, если у вас нет веских причин для этого. И никогда не смешивайте их с аннотациями CDI из javax.ejb. Это приведет к полному бесконечному списку ошибок и тонких аномалий.

Как правило, я рекомендую просмотреть первые (или даже больше) страницы превосходной страницы Документация по сварке . Это должно поставить вас на путь Java EE 6.

И не стесняйтесь размещать дополнительные вопросы здесь.

6
jan groth

Поскольку нет никаких ответов, касающихся конкретно @javax.annotation.ManagedBean, вот ссылка на ответ на аналогичный вопрос: Backing beans (@ManagedBean) или CDI Beans (@Named)? . Спецификацию можно найти по адресу http://download.Oracle.com/otndocs/jcp/managed_beans-1.0-fr-eval-oth-JSpec/ . Поэтому мне кажется, что @javax.annotation.ManagedBean должен был стать обобщением @javax.faces.bean.ManagedBean.

Из того, что я понял, JSF Managed Beans постепенно вытесняется в пользу CDI Beans (может быть, он устарел в JSF 2.3?), Поэтому я думаю, что @javax.annotation.ManagedBean становится все более устаревшим.

1
Hein Blöd