当我准备用SpringEvent优雅的解耦时,连续两个bug把我搞懵了( 二 )


文章插图
 
这时,控制台打印出了我们想要的日志 。
在创建监听事件时,一定要确保监听的Event是正确的,否则就会监听不到对应的事件 。
5,常见错误二:由于异常导致的事件传播丢失即使我们保证事件会被监听器真正的捕获,但是某些情况下,事件会因为异常导致传播丢失 。

当我准备用SpringEvent优雅的解耦时,连续两个bug把我搞懵了

文章插图
 
如上图所示,我们定义了两个Listener,原本期望按照order定义的顺序,将消息传播依次传播 。然而因为一些原因,Listener1中的方法抛出了异常,导致Listener2无法接收到消息了 。
这是因为:默认情况下处理器的执行是顺序执行的,在执行过程中,如果一个监听器执行抛出了异常,则后续监听器就得不到被执行的机会了 。
我们可以通过
SimpleApplicationEventMulticaster中的multicastEvent方法看一下事件是如何传播的,
当我准备用SpringEvent优雅的解耦时,连续两个bug把我搞懵了

文章插图
 
  
通过上图可以看出,如果在没有定义线程池的情况下,在invokeListener方法中会调用doInvokeListener方法去执行真正的逻辑,在doInvokeListener方法中,如果抛出了异常,会导致后的Listener失效 。
针对异常这种情况又该如何处理我们的代码呢?
有三种方法:
1,使用try catch捕获异常,只要Listener方法不抛出异常,自然每个Listener都可以收到广播的消息 。
2,使用@Async异步执行,通过上面的源码可以看到,如果定义的线程池,那么每一个Listener都会在一个线程中执行,每个线程之后是相互独立的,自然不会影响别人 。
3,通过ErrorHandler处理掉异常,保证后面的Listener不受影响 。
 
总结本文主要讲解了SpringEvent基本的使用方法,和平常开发中可能会遇到的一些问题 。总的来说,Spring为了让大家用的更轻松,考虑了各种可能发生的情况,但是如果大家不了解背后的实现原理,就可能发生一些本不该出现的bug 。




推荐阅读