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

107

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

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

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

Есть аннотации в javax.enterprise.contextлайках @SessionScopedи @RequestScoped.

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

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

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

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

Петр Гвязда
источник
См. Также: stackoverflow.com/questions/4684112/…
Арьян Тиймс,

Ответы:

194

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

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

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

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

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

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

Поэтому, когда вы видите слово Managed Bean, вы должны спросить о контексте или его типе (JSF, CDI, EJB и т. Д.)

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

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

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

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

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

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

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

Начнем с простейших JSF Managed beans.

Управляемые компоненты JSF

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

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

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

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

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

CDI Beans

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

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

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

    @Inject
    private SomeService someService;
}

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

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

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

EJB

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

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

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

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

@Stateless
public class BookingService {

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

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

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

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

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

Как узнать, какой фасоль использовать? Просто.

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

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

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

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

Некоторые детали украли отсюда .

Мехди
источник
3
Это круто! Спасибо! Для полноты просто расскажите, как внедрить компонент CDI или EJB в компонент JSF. Правильный ли @ManagedProperty("#{someBean})"путь?
Петр Гвязда
2
Нет! это не сработает. просто превратите свой управляемый bean-компонент jsf в управляемый bean-компонент CDI, аннотировав его с помощью @Namedи @javax.enterprise.context.RequestScopedи используйте внедрение CDI с помощью аннотации @Inject. не используйте управляемые bean-компоненты jsf, если вам это не нужно;).
Mehdi
3
> ДЖИ ребята хотят их оставить !!! - Это немного более тонко, чем это. CDI завершился довольно поздно в цикле Java EE 6, и JSF 2 и JAX-RS уже были выполнены. Они улучшили соотв. уже представили собственное управляемое средство bean. Если бы CDI был доступен немного раньше, все могло бы выглядеть иначе. В Java EE 7 JSF примет CDI, и javax.faces.bean в конечном итоге будет устаревшим (однако в Java EE устаревание - медленный процесс, что и хорошо, и плохо).
Arjan Tijms
3
Когда вы говорите: Чтобы развернуть компоненты CDI, вы должны поместить файл с именем beans.xml в папку META-INF в пути к классам. Как только вы это сделаете, каждый bean-компонент в пакете станет bean-компонентом CDI. Вы имеете в виду, что каждый компонент также становится компонентом CDI в дополнение к тому, что было? Что делать, если у меня есть JSF ManagedBeans с ManagedBean и ViewScoped. Они по-прежнему остаются управляемыми компонентами JSF, верно?
Корай Тугай
3
Кто-нибудь может обновить эту замечательную статью для Java EE 7?
Martijn Burger
7

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

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

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

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

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

Ян Грот
источник
На самом деле у меня есть два вопроса: 1. Я часто нахожу область просмотра очень полезной. Тогда мне нужно использовать аннотации JSF? 2. Это означает, что @javax.annotation.ManagedBeanэто бесполезно, поскольку CDI рассматривает все классы как управляемые компоненты, я прав?
Петр Гвязда
Не совсем. Вам нужно будет связать области JSF с CDI, например, с помощью Seam Faces. И да, @ManagedBeans не нужны, если у вас есть beans.xml в соответствующем jar-файле. О, и если у вас есть дополнительные вопросы, лучше начать новую тему, прежде чем мы потеряемся в разделе комментариев.
Ян Грот
3

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

Хайн Блод
источник
@Namedзаменим @ManagedBeanв будущем?
Туфир,
1
Я прочитал несколько заявлений разных экспертов по Java EE, которые предсказывают, что @Namedкомпоненты CDI заменят JSF @ManagedBeans, например, в stackoverflow.com/questions/4347374/… , BalusC говорит: «Ожидается, что @ManagedBean и его друзья будут устаревшими в соответствии с Java. EE 8. ".
Hein Blöd