spring ApplicationListener&ApplicationEvent

本篇主要来聊一聊spring中ApplicationListener接口和ApplicationEvent类。

从命名上可以很容易的看出来一个是listener另一个是被监听的事件,但是spring是如何做到listener去监听event?同时我们该如何在日常开发过程中使用spring为我们提供的这一个监听模式?

0x01 listener和event关系

  • spring启动后会为我们创建好一个上下文,也即是我们经常听到的spring IOC的上下文ApplicationContext,可以理解ApplicationContext中是初始化了所有在.xml文件配置的bean标签的bean。

  • 我们通过在.xml文件中定义一个listener的bean,这个listener用来监听event,listener通过实现方法com.boyu.budmw.test.AppListener#onApplicationEvent来对event进行处理。

  • listener准备好了我们可以开始向ApplicationContext中发布event,当event发布后,所有在ApplicationContext中的listener都会收到对应的event。

0x02 如何使用listener和event这一特性

  1. 定义event
    首先我们要定义一个event,不然拿什么来触发?

    public class AppEvent extends ApplicationEvent {
    
        public AppEvent(Object source) {
            super(source);
        }
    
        public void sayHi(){
            System.out.println("sayHi");
        }
    }

    定义一个event非常简单,但是需要注意,这里一定要实现带有一个参数的构造函数,因为父类ApplicationEvent中没有默认的构造方法,所以子类必须重载构造函数。

  2. 定义listener

    public class AppListener implements ApplicationListener {
    
        public void onApplicationEvent(ApplicationEvent event) {
    
            if(!(event instanceof AppEvent)){
                return ;
            }
    
            AppEvent appEvent = (AppEvent)event;
            appEvent.sayHi();
        }
    }

    上面是一个listener的实现类,listener类必须实现ApplicationListener接口,同时要实现接口中的onApplicationEvent方法,这个方法会接收到一个event,然后可以对这个event进行处理了。
    将listener类注入到spring的ApplicationContext中。<bean id="appListener" class="com.boyu.budmw.test.AppListener" />

  3. 测试listener和event

    public class ListenerTest {
    
        public static void main (String args[]){
    
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/config/applicationContext.xml");
    
            AppEvent appEvent = new AppEvent("appEvent");
    
            applicationContext.publishEvent(appEvent);
        }
    
    }

    通过org.springframework.context.ApplicationEventPublisher#publishEvent方法将event发布到spring应用上下文中,同时这个动作会触发listener收到event事件。

0x03 深入剖析发布与监听的过程

在使用org.springframework.context.ApplicationEventPublisher#publishEvent方法发布event的时候,最终会调用到spring中的org.springframework.context.event.SimpleApplicationEventMulticaster类的如下的一段代码。

当然这也是取决于你有没有对applicationEventMulticaster进行定制,如果定制了,会走到你自己定制的逻辑,下面这段是spring默认的一段逻辑。

    public void multicastEvent(final ApplicationEvent event) {
        for (final ApplicationListener listener : getApplicationListeners(event)) {
            Executor executor = getTaskExecutor();
            if (executor != null) {
                executor.execute(new Runnable() {
                    @SuppressWarnings("unchecked")
                    public void run() {
                        listener.onApplicationEvent(event);
                    }
                });
            }
            else {
                listener.onApplicationEvent(event);
            }
        }
    }
  • 这段代码一看挺简单,通过org.springframework.context.event.AbstractApplicationEventMulticaster#getApplicationListeners(org.springframework.context.ApplicationEvent)这个方法获得applicationContext中所有的listener,然后依次调用各个listener。

  • getApplicationListeners这个方法中的逻辑是从beanFactory中获取所有的ApplicationListener对象。

0x04 这个特性有什么用?

  • 当然这里也只能谈谈自己认识到的应用场景,event中可以定义一些复杂的对象或者叫服务,这样服务提供者就和服务的使用者彻底解耦了。

  • 根据自己的业务场景可以做很多事情,期待你的补充。

0x05 参考

  • 这篇我想最有参考价值的东西还是spring的源码,可以去调试相关的代码。spring有很多有价值或者说值得学习的设计思想,同样编码的规范也可以让你学到很多,多多跟着自己的思维去调试spring源码。

    原文作者:博予liutxer
    原文地址: https://segmentfault.com/a/1190000005368630
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞