Почему 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
Другие вопросы по тегам