为什么 Event.fireAsync() 需要 @ObservesAsync 注释?

Why Event.fireAsync() requires an @ObservesAsync annotation?

在 CDI 2.0 中,一个 can fire an event asynchronously 通过调用 Event.fireAsync(),然后使用 @ObservesAsync 带注释的侦听器来侦听此事件。

为什么我们需要 Event.firesAsync()@ObservesAsync

确实是个很好的问题,这里有点见识。

CDI EG(专家组)出于以下几个原因决定不混合这两者:

  • 向后兼容
    • 现有应用程序使用同步,它需要表现得一样
    • 保持相同的注释将需要您添加额外的选项以进行区分
  • Return类型
    • 调用 Event.fireAsync() 会得到一个 CompletionStage,您可以将后续步骤与 exceptionally()thenApply() 等链接起来。这自然适合异步编程模型。
    • 好旧 Event.fire() 只给你 void,你根本无法反应 - 不适合异步
    • 同样,由于向后兼容
    • ,无法更改同步的 return 值
  • 除了处理方式不同 很多
    • 同步通知异常==链结束,你炸了
    • 异步通知中的异常 == 您继续并从观察者方法(可能来自多个线程!)收集所有异常,然后将它们返回给调用代码。因为它是 CompletionStage,你可以很容易地对此做出反应。
    • 将两者混合会导致用户方面非常困惑 - 你什么时候会崩溃,什么时候继续前进? Event.fire() 的真实结果是什么(如果它也是异步的)
  • 内部观察者处理
    • 混合同步和异步会非常复杂(假设甚至可能)
    • 请记住,您需要在同步和异步之间严格划清界线,因为上下文不会在其他线程中传播(例如 RequestScoped 需要重新激活,由 Weld , 在异步观察者线程中)
    • 集成商的安全上下文传播也有类似的问题
    • 通常会对观察者进行预处理以使其工作得非常快,如果您对两者都有一个观察者方法,则无法真正对其进行预处理,因为您永远不知道它将用于什么

我能想到的当前模型的其他优点:

  • fireAsync() 的存在允许您使用其他选项触发事件
  • 最后但并非最不重要的 - 用户体验
    • 这样就很清楚了,你之前的工作完全一样
    • 而对于 fireAsync() 你有匹配的 @ObservesAsync