Де використовувати EJB 3.1 та CDI?


120

Я роблю продукт на базі Java EE, в якому я використовую GlassFish 3 та EJB 3.1.

У моїй програмі є сесійні боби , планувальник і використовуються веб-сервіси. Нещодавно я дізнався про Apache TomEE , який підтримує контексти та введення залежностей (CDI) . Контейнер GlassFish також підтримує CDI.

Чи можу я замінити сесійні боби там, де мені не потрібна функція, яку також не надає CDI? І якщо тоді, які вигоди я можу отримати?

Відповіді:


408

Так, ви можете вільно змішувати як CDI, так і EJB і досягати чудових результатів. Це здається, що ви використовуєте, @WebServiceі @Scheduleце вагомі причини для додавання EJB до суміші.

Там багато плутанини, тому ось деякі загальні відомості про EJB та CDI, як вони стосуються кожного разом.

EJB> = CDI

Зауважте, що EJB є CDI-бобами і тому мають усі переваги CDI. Зворотний неправда (поки що). Тож напевно не впадайте у звичку думати "EJB vs CDI", оскільки ця логіка справді означає "EJB + CDI vs CDI", що є дивним рівнянням.

У майбутніх версіях Java EE ми продовжуватимемо їх вирівнювати. Що поєднавши Засіб дозволяє людям робити те , що вони вже можуть зробити, тільки без @Stateful, @Statelessабо @Singletonанотації у верхній частині.

EJB та CDI в умовах реалізації

Зрештою, EJB та CDI мають однакову основоположну конструкцію компонентів проксі. Коли ви отримуєте посилання на EJB або CDI, це не справжній боб. Скоріше об'єкт, який вам дається, є підробкою (проксі). Коли ви викликаєте метод на цьому підробленому об'єкті, виклик переходить до контейнера, який буде відправляти виклик через перехоплювачі, декоратори тощо, а також піклуватися про будь-які транзакції чи перевірки безпеки. Після того, як все зроблено, виклик нарешті переходить до реального об’єкта, і результат передається назад через проксі-сервер абоненту.

Різниця полягає лише в тому, як вирішується об'єкт, на який потрібно викликати. Під "вирішеним" ми просто маємо на увазі, де і як контейнер виглядає для справжнього екземпляра, щоб викликати.

У CDI контейнер виглядає в "області", яка в основному буде хешмапом, який працює протягом певного періоду часу (за запитом @RequestScoped, за сеансом HTTP @SessionScoped, за програмою @ApplicationScoped, розмовою JSF @ConversationScopedабо за вашою спеціальною реалізацією області).

У EJB контейнер також переходить у хешмап, якщо bean має тип @Stateful. @StatefulКомпонент може також використовувати будь-який з перерахованих вище області видимості анотації , змушуючи його жити і померти з усіма іншими компонентами в обсязі. У EJB @Statefulпо суті є "будь-яка об'ємна" квасоля. В @Statelessосновному пул екземплярів - ви отримуєте екземпляр з пулу протягом часу одного виклику. По @Singletonсуті@ApplicationScoped

Отже, на фундаментальному рівні, все, що ви можете зробити з квасолею "EJB", ви повинні робити з "CDI". Під обкладинками їх важко важко розрізнити. Вся сантехніка однакова за винятком того, як вирішуються екземпляри.

Наразі вони не однакові з точки зору послуг, які контейнер буде пропонувати при виконанні цього проксі, але, як я кажу, ми працюємо над цим на рівні специфікації Java EE.

Примітка про виконання

Нехтуйте будь-якими «легкими» або «важкими» розумовими образами, які у вас можуть бути. Ось і весь маркетинг. Вони мають однаковий внутрішній дизайн здебільшого. Дозвіл примірника CDI, можливо, трохи складніший, оскільки він трохи більш динамічний і контекстуальний. Дозвіл примірника EJB є досить статичним, тупим та простим у порівнянні.

Я можу вам сказати, з точки зору впровадження в TomEE, існує приблизно нульова різниця в продуктивності між викликом EJB і викликом CDI-біна.

За замовчуванням POJO, потім CDI, потім EJB

Звичайно, не використовуйте CDI або EJB, коли користі немає. Киньте CDI, коли ви почнете бажати ін'єкцій, подій, перехоплювачів, декораторів, відстеження життєвого циклу тощо. Це найбільше часу.

Крім цих основах, існує цілий ряд корисних контейнерних послуг , які ви тільки можете використовувати , якщо ви зробите свій CDI боб також EJB, додавши @Stateful, @Statelessабо @Singletonна ньому.

Ось короткий список, коли я вибиваю EJB.

Використання JAX-WS

Розкриття JAX-WS @WebService. Я ледачий. Коли @WebServiceтакож є EJB, вам не доведеться його перераховувати та відображати у вигляді сервлету у web.xmlфайлі. Це для мене робота. Плюс я отримую можливість використовувати будь-який інший функціонал, згаданий нижче. Тож це для мене не головне.

Доступно @Statelessта @Singletonлише.

Використання JAX-RS

Розкриття ресурсу JAX-RS через @Path. Я все ще ледачий. Коли послуга RESTful також є EJB, ви знову отримуєте автоматичне виявлення і не потрібно додавати його в Applicationпідклас JAX-RS або щось подібне. Плюс я можу викрити такий самий боб, як @WebServiceякщо я хочу використовувати або використовувати будь-яку чудову функціональність, згадану нижче.

Доступно @Statelessта @Singletonлише.

Логіка запуску

Завантажте при запуску через @Startup. Наразі в CDI немає аналогічного цьому. Якось ми пропустили додати щось подібне до AfterStartupподії в життєвий цикл контейнера. Якби ми це зробили, у вас просто міг би бути @ApplicationScopedбоб, який його слухав, і це було б точно так само, як і @Singletonз @Startup. Це у списку для CDI 1.1.

Доступно @Singletonлише

Робота в паралелі

@Asynchronousвиклик методу Початкові потоки - це ні-ні в будь-якому середовищі на сервері. Занадто багато ниток - серйозний вбивця продуктивності. Ця анотація дозволяє паралелізувати речі, які ви робите, використовуючи пул потоків контейнера. Це круто.

Доступно @Stateful, @Statelessі @Singleton.

Планові роботи

@Scheduleабо ScheduleExpressionв основному це крон або Quartzфункціонал. Також дуже приголомшливий. Більшість контейнерів просто використовують для цього кварц під кришками. Однак більшість людей не знає, що робота з планування в Java EE є транзакційною! Якщо ви оновите базу даних, тоді заплануйте деяку роботу, і одна з них не вдасться, обидві будуть автоматично очищені. Якщо EntityManagerпостійний дзвінок закінчується невдало або виникає проблема змиття, не потрібно планувати роботу. Так, угоди.

Доступно @Statelessта @Singletonлише.

Використання EntityManagers в транзакції JTA

Наведена вище примітка про транзакції, звичайно, вимагає використання JTAкерованого EntityManager. Ви можете використовувати їх із звичайним "CDI", але без транзакцій, керованих контейнерами, це може отримати дійсно монотонне дублювання UserTransactionлогіки фіксації / відкату.

Доступний для всіх компонентів Java EE , включаючи CDI, JSF @ManagedBean, @WebServlet, @WebListener, @WebFilterі т.д. @TransactionAttributeанотацію, однак, доступний @Stateful, @Statelessі @Singletonтільки.

Утримання JTA керовано EntityManager

EXTENDEDВдалося EntityManagerдозволяє тримати EntityManagerвідкритими між JTAугодами і не втрачайте кешованих даних. Хороша особливість для потрібного часу та місця. Використовуйте відповідально :)

Доступно @Statefulлише

Проста синхронізація

Коли вам потрібна синхронізація, анотації @Lock(READ)та @Lock(WRITE)примітки досить чудові. Це дозволяє отримати одночасне управління доступом безкоштовно. Пропустіть всю сантехніку ReentrantReadWriteLock. У тому ж відрі є @AccessTimeout, що дозволяє сказати, скільки часу нитка повинна чекати, щоб отримати доступ до екземпляра біна, перш ніж відмовитися.

Доступно @Singletonлише для квасолі.


32
Добре небо Давиде :) Я думаю, ти це прикрив.
LightGuard

7
Дякую за цю відповідь. Ви очистили засмічення в моїй голові і з’єднали багато крапок.
Туптен

7
Це, безумовно, найкраще пояснення з цієї теми, яку я коли-небудь читав. Він також охоплює майже всі важливі аспекти EJB у використанні в реальному житті. Чудова робота!!
nanoquack

3
Дуже зрозуміло, і Адам не помиляється в суворих юридичних умовах, але відмінність суперечить. Специфікація каже, що екземпляр EJB не є контекстуальним, але потім каже, що пізніше посилання (проксі) на EJB є контекстуальним. Життєвий цикл бія Stateful повністю керується за допомогою посилання (проксі), тому, коли контейнер CDI керує цим посиланням (проксі), математика виходить однаковою - Stateful EJB можуть ефективно бути контекстними.
Девід Блевінс

3
Ви це написали на обідній перерві в TESLA?
Едісон

2

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.