CDI 2.0 中的一个can fire an event asynchronously通过调用 Event.fireAsync()
,然后使用带有 @ObservesAsync
注释的监听器来监听此事件。
为什么我们需要 Event.firesAsync()
和 @ObservesAsync
?
- CDI 2.0 不能异步处理由
Event.fire()
触发并被@ObservesAsync
捕获的事件吗? - 或者相反,为什么 CDI 2.0 不能异步处理由
Event.fireAsync()
触发并被@Observes
捕获的事件?
最佳答案
确实是一个非常好的问题,这里有一些见解。
CDI EG(专家组)出于以下几个原因决定不混合这两者:
- 向后兼容性
- 现有应用程序使用同步,它需要表现得一样
- 保持相同的注释将需要您添加额外的选项以进行区分
- 返回类型
- 调用
Event.fireAsync()
会为您提供一个CompletionStage
,您可以将后续步骤链接到该exceptionally()
或thenApply ()
等。这自然适合异步编程模型。 - 旧的
Event.fire()
只会给你void
,你根本无法对其使用react - 不利于异步 - 同样,由于向后兼容,同步的返回值不能改变
- 调用
- 除了处理很多
- 同步通知异常==链结束,你炸了
- 异步通知中的异常 == 你继续收集来自观察者方法的所有异常(可能来自多个线程!),然后将它们返回给调用代码。由于它是
CompletionStage
,您可以轻松地对此使用react。 - 混合使用这两者会导致用户方面非常困惑 - 什么时候会崩溃,什么时候继续?
Event.fire()
的真实结果是什么(如果它也是异步的)
- 内部观察者处理
- 混契约(Contract)步和异步会非常复杂(假设它甚至是可能的)
- 请记住,您需要在同步和异步之间严格划清界线,因为上下文不会在其他线程中传播(例如
RequestScoped
需要重新激活,通过焊接,在异步观察者线程中) - 集成商的安全上下文传播也存在类似的问题
- 通常会对观察者进行预处理以使其工作得非常快,如果您对两者都有一个观察者方法,则无法真正对其进行预处理,因为您永远不知道它将用于什么
我能想到的当前模型的其他优点:
fireAsync()
的存在允许您使用其他选项触发事件- 有所谓的
NotificationOptions
这允许您为您的通知指定一个执行者 - 这也为实现提供了更多火力 - Weld 已经提供了 parallel execution and timeouts通过这些选项
- 有所谓的
- 最后但并非最不重要的一点 - 用户体验
- 这样很明显,你之前的工作完全一样
- 对于
fireAsync()
你有匹配的@ObservesAsync
关于java - 为什么 Event.fireAsync() 需要 @ObservesAsync 注释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44586297/