我们知道 ApplicationContext
接口继承了ApplicationEventPublisher
接口,能够进行事件发布监听,那么什么是事件的发布跟监听呢?具体实现的原理是啥呢?本文做一个简单的记录。
监听者模式
事件源经过事件的封装传给监听器,当事件源触发事件后,监听器接收到事件对象可以回调事件的方法。
Spring 事件监听机制相关类
ApplicationEventPublisher
事件源,负责推送事件,基本都是由子类AbstractApplicationContext
完成。ApplicationEvent
事件实体,通常都是ApplicationContextEvent
及其子类。当推送的资源非ApplicationEvent
时会将资源包装成PayloadApplicationEvent
。ApplicationListener
事件监听器。ApplicationEventMulticaster
事件广播器。
执行流程
推送事件
执行 ApplicationEventPublisher
事件源的 publishEvent
方法,通常都是由当前容器 ApplicationContext
的实现类 AbstractApplicationContext#publishEvent
完成。
获取事件广播器
AbstractApplicationContext#getApplicationEventMulticaster
ApplicationEventMulticaster
基础的添加、查询、移除事件监听器的方法都已被 AbstractApplicationEventMulticaster
实现了。如果没有特别指定事件广播器,Spring 默认创建一个 SimpleApplicationEventMulticaster
实例作为事件广播器。
事件广播
SimpleApplicationEventMulticaster#multicastEvent
找到事件对应的监听器完成监听回调。如果「taskExecutor」属性值不为空则会将回调逻辑交给线程池异步执行,通过在配置类上加 @EnableAsync
注解开启异步支持,同时在事件监听方法上加 @Async
注解即可实现异步回调。
注解支持
Spring 4.2 之后可以将 @EventListener
注解加在方法上就能实现事件监听。
实现方式
Spring 是通过回调方法实现的。可以看一下SmartInitializingSingleton
接口的实现类 EventListenerMethodProcessor
,在这个类中,会先调用 afterSingletonsInstantiated
方法,然后调用 processBean
方法,在这个方法中会遍历所有容器中所有的 Bean,然后遍历 Bean 中的每一个方法判断方法上是否加了 @EventListener
注解。如果添加了这个注解,就会将这个方法包装成一个 ApplicationListenerMethodAdapter
,这个类本身也实现了 ApplicationListener
接口,之后将其添加到容器的监听器集合中。