@Inject, @EJB, @Local, @Remote, @LocalBean и т.д.:: Confused?
У меня есть следующая конфигурация:
- 1 EAR на одном GF, содержащем 2 EJB-JAR с компонентами EJB.
- 1 WAR на другом сервере Glassfish (= > другой JVM), содержащий веб-компоненты, обращающиеся к компонентам EJB.
У меня есть 2 бизнес-службы EJB в каждом EJB-JAR моего EAR, и все они развиты следующим образом:
@Remote
public interface ServiceAItf {
...
}
@Stateless
@Local
public class ServiceAImpl implements ServiceAItf {
...
}
В моей WAR я обращаюсь к компонентам EJB через явный "InitialContext.lookup" на удаленном интерфейсе.
В моем EAR я совершенно смущен лучшей практикой для инъекций с точки зрения производительности, архитектуры и т.д....
У меня есть следующие вопросы:
-
Как вы можете видеть, я объявил аннотацию "@Local" в реализации службы без определения локального интерфейса. Правильно ли это? По крайней мере, у меня нет ошибки при развертывании. Но, может быть, я должен использовать аннотацию "@LocalBean" ? Я полагаю, что аннотация "@LocalBean" просто позволяет вызывать реализацию непосредственно как "Локальный" EJB, но вы должны использовать реализацию в своем коде следующим образом:
@Stateless
@Местный
Открытый класс ServiceBImpl реализует ServiceBItf { @EJB частный сервис ServiceAImplA; ...
}
-
Каков наилучший способ вставить один EJB в другой?
Он работает следующим образом:
@Stateless
@Местный
Открытый класс ServiceBImpl реализует ServiceBItf { @EJB частная служба ServiceAItf; ...
}
Но из того, что я заметил, введенный "serviceA" - это удаленный прокси-сервер, в то время как он находится в одной JVM в одном и том же файле EAR. Поэтому я полагаю, что это повлияет на производительность. Вот почему я попытался ввести такую услугу следующим образом:
@Stateless
@Local
public class ServiceBImpl implements ServiceBItf {
@Inject
private ServiceAItf serviceA;
...
}
Но это не работает в GF, у меня есть следующее исключение:
WELD-001408 Unsatisfied dependencies for type [...] ...
Затем я попытался создать локальный интерфейс, и инъекция через аннотацию "@Inject" работает, когда обе службы
Даже если я создаю локальный интерфейс, подобный этому, служба не вводится через аннотацию "@Inject" , но имеет значение null:
@Local
public interface ServiceALocalItf {
...
}
Я прочитал много статей, в которых настоятельно рекомендуется использовать "@Inject" вместо "@EJB" , когда он предназначен для локального вызова. Это приводит меня к следующему вопросу: в этом случае рекомендуется использовать (или просто использовать) вызов EbB "@Local" ?
После всего этого анализа я пришел к следующему выводу:
- Для каждой службы я создаю интерфейс "@Local" и "@Remote" .
- От WAR до EJB-JAR EAR, сделайте поиск JNDI на удаленном интерфейсе.
- От EJB-JAR до EJB-JAR сделайте инъекцию через "@EJB" в локальный интерфейс.
- Для двух служб внутри одного EJB-JAR выполните инъекцию через "@Inject" в локальный интерфейс.
Что вы думаете об этом? Правильно ли это?
Ответы
Ответ 1
Как вы можете видеть, я объявил аннотацию "@Local" на службе реализация без определения локального интерфейса. Правильно ли это?
С EJB 3.1 требование для локальных интерфейсов было отключено. Не нужно писать их, если они явно не нужны.
Каков наилучший способ вставить один EJB в другой?
Несколько вещей, чтобы написать здесь:
С Java EE 6, Java Enterprise изменилась. Новый JSR определяет так называемый управляемый bean (не путайте с управляемым JSF beans) как своего рода минимальный компонент, который все еще может извлечь выгоду из контейнера с точки зрения управления впрыском и управления жизненным циклом. Это означает: если у вас есть компонент и "просто" хотите использовать DI и позволить контейнеру контролировать его жизненный цикл, вам не нужно использовать EJB для него. В конечном итоге вы будете использовать EJB, если - и только если - вам явно нужны функции EJB, такие как обработка транзакций, объединение, пассивация и кластеризация.
Это дает ответ на ваш вопрос в трех частях:
- Используйте @Inject over @EJB, концепция CDI (a) работает для всех управляемых
beans (сюда входят EJB), и (b) является состоятельным и, следовательно, далеко
превосходит чистый @EJB DI
- Вы уверены, что вам нужны EJB для вашего
компоненты?
- Конечно, стоит взглянуть на CDI
.
Ответ 2
@Inject
аннотация используется для java beans (POJO), а аннотация @EJB
используется для корпоративного java beans. Когда контейнер вводит ejb, предоставленный аннотацией @EJB
к другому bean, он также управляет этим жизненным циклом ejb, выполняет объединение для безстоящих beans и т.д. (Когда bean, который будет инъецирован, не разворачивается ссылка будет null). Если вы используете механизм @Inject
annotation CDI, просто найдите и создайте экземпляр инжектируемого ресурса, например, с новым оператором (если реализация интерфейса, который будет введена, не существует, ссылка будет пустой). Вы можете использовать квалификаторы с аннотацией @Inject
для выбора различной реализации внедренного интерфейса.