Spring Event 业务解耦神器,大大提高可扩展性,刷爆了!( 二 )

  • 如果异步事件抛出异常 , 则不会将其传播到调用方 。
  • 异步事件监听方法无法通过返回值来发布后续事件 , 如果需要作为处理结果发布另一个事件,请插入 ApplicationEventPublisher 以手动发布事件
  •  
    三、好处及应用场景 
    ApplicationContext 在运行期会自动检测到所有实现了 ApplicationListener 的 bean,并将其作为事件接收对象 。当我们与 spring 上下文交互触发 publishEvent 方法时,每个实现了 ApplicationListener 的 bean 都会收到 ApplicationEvent 对象 , 每个 ApplicationListener 可以根据需要只接收自己感兴趣的事件 。
    这样做有什么好处呢?
    在传统的项目中,各个业务逻辑之间耦合性比较强,controller 和 service 间都是关联关系,然而,使用 ApplicationEvent 监听 publisher 这种方式,类间关系是什么样的?我们不如画张图来看看 。
    DemoPublisher 和 DemoListener 两个类间并没有直接关联,解除了传统业务逻辑两个类间的关联关系 , 将耦合降到最小 。这样在后期更新、维护时难度大大降低了 。
    Spring Event 业务解耦神器,大大提高可扩展性,刷爆了!

    文章插图
    ApplicationEvent 使用观察者模式实现,那什么时候适合使用观察者模式呢?观察者模式也叫 发布-订阅模式 , 例如,微博的订阅,我们订阅了某些微博账号,当这些账号发布消息时,我们都会收到通知 。
    总结来说,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新 , 从而实现广播的效果 。
     
    四、源码阅读 
    Spring Event 业务解耦神器,大大提高可扩展性,刷爆了!

    文章插图
     
    Spring中的事件机制流程:
    • ApplicationEventPublisher是Spring的事件发布接口,事件源通过该接口的pulishEvent方法发布事件
    • ApplicationEventMulticaster就是Spring事件机制中的事件广播器,它默认提供一个SimpleApplicationEventMulticaster实现,如果用户没有自定义广播器,则使用默认的 。它通过父类AbstractApplicationEventMulticaster的getApplicationListeners方法从事件注册表(事件-监听器关系保存)中获取事件监听器,并且通过invokeListener方法执行监听器的具体逻辑
    • ApplicationListener就是Spring的事件监听器接口,所有的监听器都实现该接口,本图中列出了典型的几个子类 。其中RestartApplicationListnener在SpringBoot的启动框架中就有使用
    • 在Spring中通常是ApplicationContext本身担任监听器注册表的角色,在其子类AbstractApplicationContext中就聚合了事件广播器ApplicationEventMulticaster和事件监听器ApplicationListnener , 并且提供注册监听器的addApplicationListnener方法
    通过上图就能较清晰的知道当一个事件源产生事件时,它通过事件发布器ApplicationEventPublisher发布事件,然后事件广播器ApplicationEventMulticaster会去事件注册表ApplicationContext中找到事件监听器ApplicationListnener,并且逐个执行监听器的onApplicationEvent方法,从而完成事件监听器的逻辑 。
    来到ApplicationEventPublisher 的 publishEvent 方法内部:
    protected void publishEvent(Object event, @Nullable ResolvableType eventType) { if (this.earlyApplicationEvents != null) { this.earlyApplicationEvents.add(applicationEvent); } else {//getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); }}多播事件方法:
    @Overridepublic void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); Executor executor = getTaskExecutor(); // 遍历所有的监听者 for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {if (executor != null) {// 异步调用监听器executor.execute(() -> invokeListener(listener, event));}else {// 同步调用监听器invokeListener(listener, event);} }}invokeListener:
    protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) { ErrorHandler errorHandler = getErrorHandler(); if (errorHandler != null) {try {doInvokeListener(listener, event);}catch (Throwable err) {errorHandler.handleError(err);} } else {doInvokeListener(listener, event); }}doInvokeListener:
    private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) { try {// 这里是事件发生的地方listener.onApplicationEvent(event); } catch (ClassCastException ex) {...... }}


    推荐阅读