Почему Event.fireAsync() требует аннотации @ObserveAsync?
В CDI 2.0 можно вызвать событие асинхронно, вызвав Event.fireAsync()
а затем прослушать это событие с @ObservesAsync
аннотированный слушатель.
Зачем нам оба Event.firesAsync()
а также @ObservesAsync
?
- Не удалось CDI 2.0 обработать асинхронно событие, инициированное
Event.fire()
и пойман с@ObservesAsync
? - Или наоборот, почему CDI 2.0 не может асинхронно обрабатывать событие, инициированное
Event.fireAsync()
и каугут с@Observes
?
1 ответ
Решение
Очень хороший вопрос, вот немного понимания.
CDI EG (экспертная группа) решила не смешивать эти два по нескольким причинам:
- Обратная совместимость
- Существующие приложения используют синхронный, и он должен вести себя одинаково
- Сохранение той же самой аннотации потребовало бы, чтобы вы добавили дополнительную опцию, чтобы дифференцировать так или иначе
- Тип возврата
- призвание
Event.fireAsync()
дает вамCompletionStage
к которым вы можете связать следующие шаги сexceptionally()
или жеthenApply()
и т.д. Это естественно вписывается в модель асинхронного программирования. - Старый добрый
Event.fire()
только дает тебеvoid
, на который вы вообще не можете реагировать - не годится для асинхронности - Опять же, возвращаемое значение синхронного нельзя изменить из-за обратной совместимости
- призвание
- Исключая обработку сильно отличается
- Исключение в синхронном уведомлении == конец цепочки, вы взорвать
- Исключение в асинхронном уведомлении == вы продолжаете и собираете все исключения из методов наблюдателя (возможно, из нескольких потоков!), А затем представляете их обратно вызывающему коду. Так как это
CompletionStage
Вы можете легко отреагировать на это. - Смешивание этих двух факторов может привести к очень запутанному результату со стороны пользователя - когда вы взорветесь и когда продолжите? Каков истинный результат
Event.fire()
(если бы это было также для асинхронного)
- Обработка внутреннего наблюдателя
- Было бы очень сложно (при условии, что это даже возможно) смешивать синхронизацию и асинхронность
- Имейте в виду, что вам нужно строго провести линию, между которой будет происходить синхронизация и асинхронность, поскольку контексты не распространяются в других потоках (например,
RequestScoped
Сварка должна быть повторно активирована в потоке асинхронного наблюдателя) - Подобные проблемы связаны с распространением контекста безопасности для интеграторов.
- Зачастую существует предварительная обработка наблюдателей, чтобы заставить ее работать действительно быстро, если у вас есть один метод наблюдателя для обоих, вы не сможете предварительно обработать его, так как никогда не знаете, для чего он будет использоваться
Другие преимущества текущей модели, о которых я могу думать:
- Присутствие
fireAsync()
позволяет запустить событие с дополнительными опциями- Есть так называемые
NotificationOptions
которые позволяют вам указать исполнителя для ваших уведомлений - Это также дает больше возможностей для реализации - Weld уже предлагает параллельное выполнение и тайм-ауты через эти опции
- Есть так называемые
- Последнее, но не менее важное - пользовательский опыт
- Таким образом, ясно, что то, что у вас было раньше, работает точно так же
- И что за
fireAsync()
у вас есть соответствие@ObservesAsync