Ответ 1
Да, вы можете свободно смешивать CDI и EJB и добиваться отличных результатов. Похоже, вы используете @WebService
и @Schedule
, что является веским основанием для добавления EJB в микс.
Там много путаницы, так что вот некоторые общие сведения о EJB и CDI, поскольку они связаны друг с другом.
EJB >= CDI
Обратите внимание, что EJB являются CDI beans и поэтому имеют все преимущества CDI. Обратное неверно (пока). Так что определенно не привыкните думать "EJB против CDI", поскольку эта логика действительно переводит на "EJB + CDI против CDI", что является нечетным уравнением.
В будущих версиях Java EE мы продолжим их выравнивание. Какие средства выравнивания позволяют людям делать то, что они уже могут делать, просто без аннотации @Stateful
, @Stateless
или @Singleton
вверху.
EJB и CDI в условиях реализации
В конечном счете, EJB и CDI имеют одну и ту же основную схему прокси-компонентов. Когда вы получаете ссылку на EJB или CDI bean, это не реальный bean. Скорее объект, которому вы даны, является подделкой (прокси). Когда вы вызываете метод на этом поддельном объекте, вызов переходит в контейнер, который отправит вызов через перехватчики, декораторы и т.д., А также позаботится о любых транзакциях или проверках безопасности. Как только все это будет сделано, вызов, наконец, перейдет к реальному объекту, и результат будет передан обратно через прокси для вызывающего.
Разница заключается только в том, как разрешается вызов объекта. "Разрешено" мы просто имеем в виду, где и как контейнер ищет экземпляр реального экземпляра.
В CDI контейнер выглядит "областью", которая будет в основном представлять собой хэш-карту, которая живет в течение определенного периода времени (по запросу @RequestScoped
, за HTTP-сеанс @SessionScoped
, за приложение @ApplicationScoped
, разговора JSF @ConversationScoped
, или для вашей собственной реализации области видимости).
В EJB контейнер также смотрит на хэш-карту, если bean имеет тип @Stateful
. @Stateful
bean также может использовать любую из вышеупомянутых аннотаций области, заставляя его жить и умирать со всеми остальными beans в области. В EJB @Stateful
есть, по существу, "любая область действия" bean. @Stateless
- это в основном пул экземпляров - вы получаете экземпляр из пула в течение одного вызова. @Singleton
по существу @ApplicationScoped
Итак, на фундаментальном уровне все, что вы можете сделать с помощью "EJB" bean, вы должны иметь возможность сделать с "CDI" bean. Под обложками ужасно сложно рассказать им обособленно. Все сантехника одинакова, за исключением того, как разрешены экземпляры.
В настоящее время они не совпадают с услугами, которые контейнер предложит при выполнении этого проксирования, но, как я уже сказал, мы работаем над этим на уровне спецификации Java EE.
Замечание по производительности
Не обращайте внимания на любые "легкие" или "тяжелые" ментальные образы, которые у вас могут быть. Это весь маркетинг. У них такой же внутренний дизайн по большей части. Реализация экземпляра CDI, возможно, немного сложнее, потому что она немного более динамична и контекстуальна. Разрешение экземпляра EJB довольно простое, немое и простое сравнение.
Я могу рассказать вам с точки зрения реализации в TomEE, там около нулевой разницы в производительности между вызовом EJB и вызовом CDI bean.
По умолчанию POJO, затем CDI, затем EJB
Конечно, не используйте CDI или EJB, когда нет никакой пользы. Бросьте CDI, когда вы начинаете хотеть инъекции, события, перехватчики, декораторы, отслеживание жизненного цикла и тому подобное. Это самое время.
Помимо этих основ, существует множество полезных контейнерных сервисов, которые вы можете использовать только в том случае, если вы сделаете свой CDI bean также EJB, добавив в него @Stateful
, @Stateless
или @Singleton
.
Вот краткий список, когда я вырываю EJB.
Использование JAX-WS
Воздействие JAX-WS @WebService
. Мне лень. Когда @WebService
также является EJB, вам не нужно перечислить его и сопоставить его как сервлет в файле web.xml
. Это работает для меня. Плюс я получаю возможность использовать любую из других функций, упомянутых ниже. Поэтому для меня это не проблема.
Доступно только для @Stateless
и @Singleton
.
Использование JAX-RS
Предоставление ресурса JAX-RS через @Path
. Я все еще ленив. Когда служба RESTful также является EJB, вы снова получаете автоматическое обнаружение и не должны добавлять ее в подкласс JAX-RS Application
или что-то в этом роде. Плюс я могу показать тот же самый bean как @WebService
, если я хочу или использовать любую из замечательных функций, упомянутых ниже.
Доступно только для @Stateless
и @Singleton
.
Логика запуска
Загрузка при запуске через @Startup
. В настоящее время в CDI нет эквивалента. Как-то мы пропустили добавление чего-то типа события AfterStartup
в жизненный цикл контейнера. Если бы мы это сделали, у вас просто мог бы быть @ApplicationScoped
bean, который слушал его, и это было бы фактически так же, как @Singleton
с @Startup
. Это в списке для CDI 1.1.
Доступно только для @Singleton
.
Работа в параллельном режиме
@Asynchronous
вызов метода. Начальные потоки - это не-no в любой серверной среде. Слишком много потоков - серьезный убийца. Эта аннотация позволяет вам распараллелить все, что вы делаете, используя пул потоков контейнера. Это круто.
Доступно для @Stateful
, @Stateless
и @Singleton
.
Планирование работы
@Schedule
или ScheduleExpression
- это в основном функциональность cron или Quartz
. Также очень классно. В большинстве контейнеров для этого используется кварц. Однако большинство людей не знает, что планирование работы в Java EE является транзакционным! Если вы обновляете базу данных, тогда планируете какую-то работу, и один из них не работает, оба будут автоматически очищены. Если вызов EntityManager
persist завершается с ошибкой или возникает проблема очистки, нет необходимости расфанировать работу. Yay, транзакции.
Доступно только для @Stateless
и @Singleton
.
Использование EntityManager в транзакции 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
, который позволяет вам сказать, сколько времени должен ждать поток, чтобы получить доступ к экземпляру bean перед тем, как сдаться.
Доступно только для @Singleton
beans.