4

在 CDI 2.0中,可以通过调用异步触发事件Event.fireAsync(),然后使用带@ObservesAsync注释的侦听器侦听此事件。

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

  • CDI 2.0 不能异步处理由 触发Event.fire()和捕获的事件@ObservesAsync吗?
  • 或者反过来说,为什么 CDI 2.0 不能异步处理由Event.fireAsync()cauguth with触发的事件@Observes
4

1 回答 1

10

确实是一个非常好的问题,这里有一点见解。

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

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

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

  • Presence offireAsync()允许您使用其他选项触发事件
  • 最后但并非最不重要的——用户体验
    • 这样很明显,您之前的工作方式完全相同
    • 这对fireAsync()你来说有匹配的@ObservesAsync
于 2017-06-16T11:58:24.243 回答