Так, ви можете вільно змішувати як 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
лише для квасолі.