Java EE 6 @javax.annotation.ManagedBean против @javax.inject.Named против @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 вводить другие бобы?

3 ответа

Решение

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

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

В Java ee у нас есть много контейнеров, которые управляют жизненным циклом своих объектов, таких как контейнер 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-контейнером, но все же он не был полным и зрелым контейнером.

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

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

JSF Managed Beans, CDI Beans и EJB

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

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

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

JSF Managed Beans

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

Они могут быть определены с помощью @javax.faces.bean.ManagedBean аннотация, которая принимает необязательный параметр имени. Это имя может использоваться для ссылки на 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 пакет (а именно, области запроса, разговора, сеанса и приложения). Если вы хотите использовать компонент CDI со страницы JSF, вы можете дать ему имя, используя javax.inject.Named аннотаций. Чтобы внедрить бин в другой боб, вы аннотируете поле с помощью 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 для сопоставления его с точкой внедрения.

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

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

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

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

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

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

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

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

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

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

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

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

Поскольку нет никаких ответов конкретно о @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 тем более устаревает сейчас.

Другие вопросы по тегам