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


107

Я відчуваю, що в специфікації 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вводити інші боби?


Відповіді:


194

Перш за все, дозвольте мені зробити пояснення:

Визначення керованої квасолі : загалом керована квасоля - це об'єкт, яким її життєвий цикл (будівництво, знищення тощо) керує контейнер.

У Java ee у нас є багато контейнерів, які керують життєвим циклом їх об'єктів, як контейнер JSF, контейнер EJB, контейнер CDI, контейнер Servlet тощо.

Усі ці контейнери працюють на зразок незалежних, вони завантажуються в ініціалізацію сервера додатків і сканують класи всіх артефактів, включаючи jar, ejb-jar, файли війни та вух у час розгортання, збирають і зберігають деякі метадані про них, тоді коли вам потрібен об'єкт класу під час виконання вони дадуть вам екземпляри цих класів, і після закінчення завдання вони знищать їх.

Тож можна сказати, що у нас є:

  • JSF керували квасолею
  • CDI керували квасолею
  • EJB керувала квасолею
  • І навіть сервлетами керують боби, тому що вони інстанціровані і знищені контейнером, який є контейнером із сервлетами.

Отже, коли ви бачите слово керованого квасолі, вам слід запитати про його контекст або тип. (JSF, CDI, EJB тощо)

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

У той же час (паралельно) вони зрозуміли, що їм також потрібно підтримувати JSF, тоді вони зробили боби з JSF, які керували JSF, та іншу ємність для бобів JSF, і вважали це зрілим контейнером DI, але все-таки це не повний та зрілий контейнер.

Після цього Гевін Кінг та деякі інші приємні хлопці;) зробили 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.

Керовані квасолею JSF

Якщо коротко, не використовуйте їх, якщо ви розробляєте для Java EE 6 і використовуєте CDI. Вони забезпечують простий механізм введення залежності та визначення резервних бобів для веб-сторінок, але вони набагато менш потужні, ніж CDI.

Вони можуть бути визначені за допомогою @javax.faces.bean.ManagedBeanпримітки, яка приймає необов'язковий параметр імені. Ця назва може використовуватися для посилання на квасоля зі сторінок JSF.

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

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

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

CDI квасоля

CDI - це система управління бобами та введення залежностей, яка була випущена у складі Java EE 6, і вона включає в себе повне, всебічне управління квасолею. CDI-боби набагато досконаліші та гнучкіші, ніж прості боби, керовані JSF. Вони можуть використовувати перехоплювачі, сферу розмови, події, тип безпечної ін'єкції, декоратори, стереотипи та методи виробників.

Для розгортання бобів CDI потрібно розмістити файл, який називається beans.xml, у папці META-INF на classpath. Як тільки ви це зробите, то кожна квасоля в упаковці стає квасолею 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 обробляє ін'єкцію квасолі з невідповідними сферами застосування проксі. Через це ви можете ввести бій, на якому розміщено запит, у бін, що охоплює сеанс, і посилання все одно буде дійсною для кожного запиту, оскільки для кожного запиту проксі повторно підключається до живого екземпляра запиту.

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

EJB

EJB передують квасолі CDI і подекуди схожі на 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 боби сильно відрізняються за характеристиками, написання коду для їх інтеграції дуже схоже, оскільки CDI-боби можна вводити в EJB, а EJB можна вводити в CDI-боби. Не потрібно робити жодних розбіжностей при введенні одного в інший. Знову ж таки, різними сферами застосування займаються CDI шляхом використання проксі. Винятком з цього є те, що CDI не підтримує ін'єкцію віддалених EJB, але це може бути реалізовано, написавши для цього простий метод виробника.

javax.inject.NamedАнотацій, а також будь-які Міський турнір можуть бути використані на EJB , щоб відповідати його до точки уприскування.

Коли використовувати який квасоля

Як ви знаєте, коли вживати який боб? Простий.

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

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

Якщо вам потрібно використовувати @ViewScopedCDI, вам слід

  • використовувати шви граней або модуль MyFaces CODI . просто додайте одну з них на свій класний шлях і @ViewScopedбуде працювати в CDI. MyFaces CODI має ще більш надійну підтримку @ViewScoped
  • використовуйте CODI MyFaces @ViewAccessScoped, це розширення, написане Apache на CDI поверх CDI, просто завантажте його та @ViewAccessScopedзамість цього використовуйте анотацію @ViewScoped.
  • Використовуйте CDI @ConversationScopedі зробіть його тривалим. Дивіться тут для отримання додаткової інформації .
  • Використовуйте примітки Omniface @ViewScoped

Деякі частини розкрадаються звідси .


3
Це чудово! Дякую! Щоб завершити, просто розкажіть, як ввести CDI або EJB в зерно JSF. Чи @ManagedProperty("#{someBean})"правильний шлях?
Piotr Gwiazda

2
Ні! це не спрацює. просто перетворити керований компонент JSF в КДІ керованого компонента шляхом анотування його з допомогою @Namedі @javax.enterprise.context.RequestScopedта ін'єкція використання CDI з допомогою @Inject анотації. не використовуйте jsf керовані боби, якщо вам не доведеться;).
Мехді

3
> Хлопці JEE хочуть зберегти їх !!! - Це трохи тонкіше за це. CDI закінчився досить пізно в циклі Java EE 6, і JSF 2 і JAX-RS вже були готові. Вони мали розширений респ. вже запровадили власний керований об'єкт бобів. Якби CDI була доступна трохи раніше, все могло б виглядати інакше. У Java EE 7 JSF прийме CDI, а javax.faces.bean врешті-решт буде застарілий (депрекація - це повільний процес у Java EE, хоча це і добре, і погано).
Арджан Тіджмс

3
Коли ви говорите: Щоб розгорнути CDI-боби, ви повинні розмістити файл, який називається beans.xml, у папці META-INF на classpath. Як тільки ви це зробите, то кожна квасоля в упаковці стає квасолею 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 ставиться до всіх класів як до керованих бобів, я прав?
Piotr Gwiazda

Не зовсім. Вам потрібно буде встановити діапазони JSF до CDI за допомогою, наприклад, обличчя шва. І так, @ManagedBeans не потрібні, якщо у вас є файл beans.xml у відповідному jar-файлі. О, і якщо у вас є додаткові запитання, краще розпочати нову тему, перш ніж ми втратимо себе в розділі коментарів.
Ян Грот

3

Оскільки відповідей конкретно про це немає @javax.annotation.ManagedBean, ось посилання на відповідь на подібне запитання: Береження бобів (@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 Beans (можливо, застаріла від JSF 2.3?), Тож я здогадуюсь, що @javax.annotation.ManagedBeanзараз все застаріло.


@Namedзамінить @ManagedBeanу майбутньому?
Туфір

1
Я прочитав кілька заяв різних експертів Java EE , які пророкують , що КДІ @Namedбоби замінить JSF @ManagedBeans, наприклад , в stackoverflow.com/questions/4347374 / ... , BalusC каже : «Очікується, що @ManagedBean і друзі будуть небажані на Java EE 8. ".
Хайн Блёд
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.