Java EE 6 @javax.annotation.ManagedBean vs. @javax.inject.Named vs. @javax.faces.ManagedBean

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

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

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

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

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

И чтобы усложнить ситуацию, есть пакет javax.inject с аннотацией @Named.

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

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

Ответ 1

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

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

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

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

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

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

Итак, когда вы видите управляемое слово bean, вы должны спросить о его контексте или типе (JSF, CDI, EJB и т.д.)

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

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

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

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

JSF Управляемый Beans, CDI beans и EJBs

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

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

Давайте начнем с простейшего управляемого JSF beans.

Управляемый JSF beans

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

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

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

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

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

CDI beans

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

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

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

    @Inject
    private SomeService someService;
}

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

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

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

EJB

EJBs predate CDI beans и находятся в чем-то подобном CDI beans и другими способами очень различны. Прежде всего, различия между CDI beans и EJB состоят в том, что EJB:

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

Два типа EJB называются stateless и stateful. Безстоящие EJB можно рассматривать как поточно-безопасные одноразовые beans, которые не поддерживают какое-либо состояние между двумя веб-запросами. Stateful EJBs сохраняют состояние и могут создаваться и сидеть, пока они нужны, до тех пор, пока они не будут удалены.

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

@Stateless
public class BookingService {

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

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

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

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

Когда использовать bean

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

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

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

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

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

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

Ответ 2

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

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

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

Обычно я рекомендую вам пропустить первые несколько (или даже более) страниц отличной документации Weld. Это должно поставить вас на путь для Java EE 6.

И не стесняйтесь публиковать дополнительные вопросы здесь.

Ответ 3

Поскольку нет специальных сообщений о @javax.annotation.ManagedBean, здесь ссылка на ответ аналогичного вопроса: Резервное копирование beans (@ManagedBean) или CDI beans (@Названный)?. Спектр можно найти в 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 тем временем становится устаревшим.