public String paymentType;
public BigDecimal value;
public Date datetime;
public PaymentEvent() {
}
Java Platform, Enterprise Edition (Java EE) 8 Учебник по Java EE |
Назад | Вперёд | Содержание |
События позволяют бинам взаимодействовать без какой-либо взаимозависимости объектов во время компиляции. Один компонент может определять событие, другой компонент может вызывать событие, и ещё один компонент может обрабатывать событие. Кроме того, события могут быть запущены асинхронно. Бины могут быть в разных пакетах и даже в разных слоях приложения.
Событие состоит из следующего:
Объект события
Ноль или более типов квалификаторов
Например, в примере billpayment
, описанном в Пример billpayment: использование событий и Interceptor-ов, бин PaymentEvent
определяет событие, используя три свойства, для которых есть set- и get- методы:
public String paymentType;
public BigDecimal value;
public Date datetime;
public PaymentEvent() {
}
В этом примере также определяются квалификаторы, которые различают два вида PaymentEvent
. Каждое событие также имеет квалификатор по умолчанию @Any
.
Обработчик событий использует метод-наблюдатель для получения событий.
Каждый метод-наблюдатель принимает в качестве параметра событие определённого типа, аннотированное @Observes
и любыми квалификаторами для этого типа события. Метод-наблюдатель уведомляется о событии, если объект события соответствует типу события и если все квалификаторы события соответствуют квалификаторам события метода-наблюдателя.
Метод-наблюдатель может принимать другие параметры в дополнение к параметру события. Дополнительные параметры являются точками инъецирования и могут объявлять квалификаторы.
Обработчик события PaymentHandler
для примера billpayment
определяет два метода-наблюдателя, по одному для каждого типа PaymentEvent
:
public void creditPayment(@Observes @Credit PaymentEvent event) {
...
}
public void debitPayment(@Observes @Debit PaymentEvent event) {
...
}
Методы-наблюдатели также могут быть условными или транзакционными:
Условный метод-наблюдатель уведомляется о событии, только если объект компонента, который определяет метод-наблюдатель, уже существует в текущем контексте. Чтобы объявить условный метод-наблюдатель, укажите notifyObserver=IF_EXISTS
в качестве аргумента для @Observes
:
@Observes(notifyObserver=IF_EXISTS)
Чтобы получить безусловное поведение по умолчанию, можно указать @Observes(notifyObserver=ALWAYS)
.
Транзакционный метод-наблюдатель уведомляется о событии до или после завершения транзакции, в которой произошло событие. Можно также указать, что уведомление должно появляться только после успешного или неудачного завершения транзакции. Чтобы указать метод-наблюдатель транзакции, используйте любой из следующих аргументов для @Observes
:
@Observes(during=BEFORE_COMPLETION)
@Observes(during=AFTER_COMPLETION)
@Observes(during=AFTER_SUCCESS)
@Observes(during=AFTER_FAILURE)
Чтобы получить стандартное нетранзакционное поведение по умолчанию, укажите @Observes(during=IN_PROGRESS)
.
Метод-наблюдатель, который вызывается до завершения транзакции, может вызвать метод setRollbackOnly
в объекте транзакции, чтобы вызвать откат транзакции.
Методы-наблюдатели могут генерировать исключения. Если транзакционный метод-наблюдатель выдает исключение, это исключение перехватывается контейнером. Если метод-наблюдатель не является транзакционным, исключение завершает обработку события, и никакие другие методы-наблюдатели для события не вызываются.
Прежде чем генерируется определённое уведомление наблюдателя о событии, контейнер определяет порядок вызова методов-наблюдателей для этого события. Порядок методов-наблюдателей устанавливается посредством объявления аннотации @Priority
для параметра события метода-наблюдателя, как в следующем примере:
void afterLogin(@Observes @Priority(javax.interceptor.Interceptor.Priority.APPLICATION) LoggedInEvent event) { ... }
Обратите внимание на следующее:
Если аннотация @Priority
не указана, значением по умолчанию является javax.interceptor.Interceptor.Priority.APPLICATION + 500
.
Если двум или более методам-наблюдателям назначен одинаковый приоритет, порядок их вызова не определён и поэтому непредсказуем.
Бин генерирует события, реализующие интерфейс javax.enterprise.event.Event
. События могут быть сгенерированы синхронно или асинхронно.
Чтобы активировать событие синхронно, вызовите метод javax.enterprise.event.Event.fire
. Этот метод генерирует событие и уведомляет любые методы-наблюдатели.
В примере billpayment
Managed-бин PaymentBean
запускает соответствующее событие, используя информацию, полученную из пользовательского интерфейса. На самом деле существует четыре компонента событий, два для объекта события и два для выполнения содержательной части. Managed-бин инъецирует два бина события. Метод pay
использует оператор switch
для выбора события, которое нужно запустить, используя new
для выполнения содержательной части.
@Inject
@Credit
Event<PaymentEvent> creditEvent;
@Inject
@Debit
Event<PaymentEvent> debitEvent;
private static final int DEBIT = 1;
private static final int CREDIT = 2;
private int paymentOption = DEBIT;
...
@Logged
public String pay() {
...
switch (paymentOption) {
case DEBIT:
PaymentEvent debitPayload = new PaymentEvent();
// выполнение содержательной части...
debitEvent.fire(debitPayload);
break;
case CREDIT:
PaymentEvent creditPayload = new PaymentEvent();
// выполнение содержательной части...
creditEvent.fire(creditPayload);
break;
default:
logger.severe("Invalid payment option!");
}
...
}
Аргументом метода fire
является PaymentEvent
, который включает содержательная часть. Инициированное событие затем используется методами-наблюдателями.
Чтобы активировать событие асинхронно, вызовите метод javax.enterprise.event.Event.fireAsync
. Этот метод вызывает все разрешённые асинхронные наблюдатели в одном или нескольких разных потоках.
@Inject Event<LoggedInEvent> loggedInEvent;
public void login() {
...
loggedInEvent.fireAsync( new LoggedInEvent(user) );
}
Вызов метода fireAsync()
возвращается немедленно.
Когда события запускаются асинхронно, методы-наблюдатели уведомляются асинхронно. Следовательно, соблюдение порядка методов-наблюдателей не гарантировано, потому что вызов метода-наблюдателя и запуск асинхронных событий происходят в разных потоках.
Назад | Вперёд | Содержание |