Как сравнить CDI и EJB? взаимодействовать?

106

Мне сложно понять, как они взаимодействуют и где проходит граница между ними. Они перекрываются? Есть ли между ними дублирование?

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

На самом деле просто запутались. Я (думаю, я) достаточно хорошо понимаю EJB, полагаю, мне трудно понять, что именно CDI приносит на стол и как он заменяет или улучшает то, что уже предлагает EJB.

Тим
источник
3
Этот вопрос занимает первое место в поиске Google «Разница в EJB CDI», но я нашел ответ на stackoverflow.com/questions/13487987/… яснее
matt freake

Ответы:

50

CDI: речь идет о внедрении зависимостей. Это означает, что вы можете внедрить реализацию интерфейса где угодно. Этот объект может быть чем угодно, он не может быть связан с EJB. Вот пример того, как внедрить случайный генератор с помощью CDI. Про EJB ничего нет. Вы собираетесь использовать CDI, когда хотите внедрить не-EJB-сервисы, различные реализации или алгоритмы (так что вам вообще не нужен EJB).
EJB: вы понимаете, и, вероятно, вас смущает @EJBаннотация - она ​​позволяет вам внедрить реализацию в вашу службу или что-то еще. Основная идея заключается в том, что класс, в который вы вводите, должен управляться контейнером EJB. Кажется, что CDI понимает, что такое EJB, поэтому на сервере, совместимом с Java EE 6, в своем сервлете вы можете написать как

@EJB EJBService ejbService;

и

@Inject EJBService ejbService;

это то, что может сбить вас с толку, но это, вероятно, единственное, что является мостом между EJB и CDI.

Когда мы говорим о CDI, вы можете внедрять другие объекты в классы, управляемые CDI (они просто должны быть созданы фреймворками, поддерживающими CDI).

Что еще предлагает CDI ... Например, вы используете Struts 2 в качестве среды MVC (просто пример), и здесь вы ограничены, даже используя EJB 3.1 - вы не можете использовать @EJBаннотацию в действии Struts, она не управляется контейнером. Но когда вы добавляете плагин Struts2-CDI, вы можете написать там @Injectаннотацию для того же самого (так что больше не требуется поиск JNDI). Таким образом, он увеличивает мощность EJB, но, как я упоминал ранее, то, что вы вводите с помощью CDI - не имеет значения, связано это с EJB или нет, и в этом его сила.

PS. обновленная ссылка на пример

Maxym
источник
Действительно ли @EJB и @Inject функционально эквивалентны? Я думаю, что меня смутило совпадение методов внедрения между CDI и некоторыми другими аббревиатурами Java EE. Дополнительное чтение, кажется, указывает на то, что есть надежда выровнять аннотации.
Тим
@Maxym Когда вы используете @ Inject, как вы можете гарантировать, что @ Stateless или любой другой компонент EJB на стороне сервера по-прежнему использует такие функции, как объединение в пул или параллелизм, предлагаемые контейнером. Надеюсь, CDI не предлагает этого, верно?
Бала,
1
@Bala: CDI не предлагает пулы ... посмотрите на CDI с EJB3.1 или без него , надеюсь, он ответит на ваш вопрос ..
Maxym
@KorayTugay: CDI - это функция Java EE, поэтому она есть на любом сервере, совместимом с Java EE 6 (Glassfish 3.0.1+ не ошибается, JBoss 6+ и т. Д.). Вы можете взглянуть на JBoss Weld, эталонную реализацию CDI, которую вы можно использовать, например, в Tomcat ...
Maxym
191

В настоящее время это действительно немного сбивает с толку, поскольку в Java EE теперь есть несколько компонентных моделей. Это управляемые объекты CDI , EJB3 и JSF .

CDI - новичок в этом квартале. КДИ бобы имеют dependency injection, scopingи event bus. Компоненты CDI являются наиболее гибкими в отношении внедрения и определения объема. Шина событий очень легкая и очень хорошо подходит даже для самых простых веб-приложений. В дополнение к этому, CDI также предоставляет очень продвинутую функцию под названием portable extensions, которая представляет собой своего рода механизм подключаемых модулей для поставщиков, обеспечивающий дополнительные функции для Java EE, которые могут быть доступны во всех реализациях (Glassfish, JBoss AS, Websphere и т. Д.) .

Компоненты EJB3 были модернизированы из старой устаревшей компонентной модели EJB2 * и были первыми компонентами в Java EE, которыми можно было управлять через аннотацию. EJB3 бобы имеют dependency injection, declarative transactions, declarative security, pooling, concurrency control, asynchronous executionи remoting.

Внедрение зависимостей в bean-компонентах EJB3 не так гибко, как в bean-компонентах CDI, а EJB3-компоненты не имеют концепции области видимости. Однако bean-компоненты EJB3 являются транзакционными и по умолчанию объединяются в пулы ** , две очень полезные вещи, которые CDI решил оставить в домене EJB3. Остальные упомянутые элементы также недоступны в CDI. У EJB3 нет собственной шины событий, но есть специальный тип bean-компонента для прослушивания сообщений; управляемый сообщениями компонент. Его можно использовать для получения сообщений от системы обмена сообщениями Java или от любой другой системы, имеющей адаптер ресурсов JCA. Использование полнофункционального обмена сообщениями для простых событий намного сложнее, чем шина событий CDI, а EJB3 определяет только прослушиватель, а не API производителя.

Управляемые компоненты JSF существуют в Java EE с момента включения JSF. В них тоже есть особенность dependency injectionи scoping. Управляемые компоненты JSF представили концепцию декларативной области действия. Первоначально возможности были довольно ограничены, и в той же версии Java EE, где компоненты EJB3 уже могли быть объявлены с помощью аннотаций, управляемые компоненты JSF по-прежнему должны были быть объявлены в XML. Текущая версия управляемых компонентов JSF также наконец объявляется с помощью аннотации, а области действия расширяются за счет области представления и возможности создавать настраиваемые области. Область представления, которая запоминает данные между запросами к одной и той же странице, является уникальной особенностью управляемых компонентов JSF.

Помимо области представления, для управляемых компонентов JSF в Java EE 6 еще очень мало возможностей. Отсутствие области представления в CDI вызывает сожаление, поскольку в противном случае CDI был бы идеальным суперсистемой того, что предлагают управляемые компоненты JSF. Обновление : в Java EE 7 / JSF 2.2 был добавлен CDI-совместимый @ViewScoped , что делает CDI действительно идеальным супер-набором. Обновление 2 : в JSF2.3 управляемые компоненты JSF устарели в пользу управляемых компонентов CDI.

С EJB3 и CDI ситуация не так однозначна. Компонентная модель и API EJB3 предлагают множество сервисов, которые не предлагает CDI, поэтому обычно EJB3 не может быть заменен CDI. С другой стороны, CDI можно использовать в сочетании с EJB3 - например, добавляя поддержку области действия к EJB.

Реза Рахман, член группы экспертов и разработчик реализации CDI под названием CanDI, часто намекал, что службы, связанные с компонентной моделью EJB3, могут быть модифицированы в виде набора аннотаций CDI. Если бы это произошло, все управляемые компоненты в Java EE могли бы стать компонентами CDI. Это не означает, что EJB3 исчезнет или станет устаревшим, просто его функциональность будет представлена ​​через CDI, а не через собственные аннотации EJB, такие как @Stateless и @EJB.

Обновить

Дэвид Блевинс из TomEE и OpenEJB очень хорошо объясняет различия и сходства между CDI и EJB в своем блоге: CDI, когда выделять EJB

* Хотя это всего лишь приращение номера версии, EJB3 beans по большей части был совершенно другим типом bean: простой pojo, который становится «управляемым bean-компонентом» путем применения простой единственной аннотации, по сравнению с моделью в EJB2, где тяжелые и слишком подробный дескриптор развертывания XML требовался для каждого bean-компонента, в дополнение к bean-компоненту, который требовался для реализации различных чрезвычайно тяжелых и по большей части бессмысленных интерфейсов компонентов.

** Сессионные компоненты без сохранения состояния обычно объединяются в пулы, а сеансовые компоненты с сохранением состояния - нет (но могут быть). Таким образом, для обоих типов пул необязателен, и спецификация EJB в любом случае не требует этого.

Арьян Тиймс
источник
3
Меня немного смущают ваши утверждения о том, что «EJB3 beans не имеет концепции области видимости» и что «EJB3 не имеет собственной шины событий». Как это согласуется с утверждением Дэвида Блевина о том, что «EJB- компоненты являются компонентами CDI и, следовательно, обладают всеми преимуществами CDI»? Изменилось ли что-нибудь в этом отношении между тем, когда вы написали свой ответ, и тем, когда Дэвид написал свою запись в блоге?
Крис
5
Это из-за, возможно, несколько сбивающей с толку концепции, что на самом деле «компонентов CDI» нет, но есть службы, применяемые к управляемым компонентам. В целях обсуждения люди (и я, таким образом) в любом случае называют их «компонентами CDI». До CDI компоненты EJB не имели явной области видимости. Как объясняет Дэвид, Stateful неявно подразумевает любую область видимости (и, следовательно, не имеет конкретной области видимости). с доступным CDI компоненты EJB могут использовать преимущества предоставленных CDI областей действия. Без спецификации CDI, поэтому, если смотреть исключительно на спецификацию EJB, нет явных областей действия.
Арджан Тиджмс
1
Не могли бы вы пояснить, что вы подразумеваете под «есть службы, применяемые к управляемым bean-компонентам»? Означает ли это, что на самом деле не существует компонента CDI? Это просто некоторые из дополнительных возможностей POJO - EJB - или JSF Managed Bean? Нравится использовать аннотацию Inject в управляемом компоненте JSF?
Корай Тугай
3
@Chris для дальнейшего пояснения с точки зрения спецификации EJB, мы приняли сознательное решение с самого начала CDI требовать, чтобы реализации EJB поддерживали 100% набора функций CDI в EJB. Каждый аспект CDI работает с EJB, за исключением областей, которые нам пришлось ограничить только компонентами с отслеживанием состояния.
Дэвид Блевинс
1
Обратите внимание, что JSF 2.2 теперь предоставляет javax.faces.view.ViewScoped, расширение CDI, которое, по сути, является портом области представления JSF для CDI. При этом CDI является полной заменой управляемых компонентов JSF.
jdessey 03
-1

Альберт Эйнштейн: If you can't explain it simply, you don't understand it well enough

Ejbs и CDI довольно просты для понимания.

Ejbs:

  1. Всегда будет аннотироваться квалификаторами области видимости, например, @Stateless, @Stateful, @Request и т. Д.
  2. Экземпляры Ejbs управляются платформой Java EE и объединяются в пул. Обязанность инфраструктуры EE - предоставить экземпляры для потребителя.

@Stateless

 public class CarMaker(){
    public void createCar(Specification specs){
        Car car = new Car(specs);
    }
}

CarMaker имеет аннотацию с указанием конкретной области действия Ejbs, поэтому это Ejb

CDI:

  1. Не полностью управляемые платформой EE, экземпляры необходимо создавать самостоятельно.
  2. Это всегда зависимо. позвольте мне объяснить «Зависимый» на примере:

    class Specification { private String color; private String model; //- Getter and Setter }

Это Specificationкласс CDI, поскольку он не аннотирован областями действия Ejb, а также должен быть инициализирован вашим кодом, а не структурой EE. Здесь следует отметить один момент: поскольку мы не аннотировали Specificationкласс, он по умолчанию @Dependentаннотируется аннотацией.

@Dependent  <- By default added 
class Specification { ... }

Further reading: Вам нужно больше изучить аннотацию области видимости Ejbs и аннотацию области действия CDI, что еще больше прояснит концепцию.

HA S
источник
Эйнштейн также сказал: «Все должно быть сделано как можно проще, но не проще», вы можете (должны) заменить здесь «сделано» на «объяснено».
Kukeltje