深入了解 Spring 之事件机制
一. 概述
在深入了解 Spring 之上下文大体介绍了 ApplicationContext 启动过程中关键的几个步骤;在 AbstractApplicationContext 中,有三个关键属性成员,如下:
applicationEventMulticaster 事件的传播者
applicationListeners 监听器集合
earlyApplicationEvents 早期上下文启动过程中触发的事件;
这三个属性成员就是这篇所要介绍的内容,事件机制;
这里,我们带着问题去了解:
工作机制是什么样的?
事件是如何触发的?
事件是如何传播的?
监听器是如何添加的?
二. 概念及原理
事件机制,涉及到几大概念,事件、发布者、观察者、监听者,,其采用的模式是观察者模式;这个时候,值得推荐的刘伟大佬的文章,非常值得一读,通俗介绍了观察者模式,以及大体的原理,这里就不在班门弄斧;
整个设计模式完整版,史上最全设计模式导学目录(完整版)
三. spring 实现
1. 事件
在 spring 中,抽象类为 ApplicationEvent,该抽象类有两个成员属性
timestamp 记录事件的生产时间戳
source 事件所携带的对象,该对象是 Object,意味我们我们可以传递任意的类型;
在 spring 中,有几大关键的子类,涉及到从容器启动到初始化完成的事件对象;
ContextClosedEvent spring 容器关闭事件
ContextRefreshedEvent spring 容器的初始化后或者刷新完成事件;具体代码如下
ContextStoppedEvent spring 容器停止事件
ContextStartedEvent spring 容器初始化开始事件
ContextStartedEvent 于 ContextStoppedEvent 是有关 Lifecycle 的事件;而 ContextClosedEvent 是有关整个 spring 容器销毁;
下面是有关 spring boot 所拓展的事件
ApplicationEnvironmentPreparedEvent 容器环境对象初始化后的事件
ApplicationPreparedEvent 容器初始化前的事件,主要是在做 refresh 动作之前做触发的事件
ApplicationStartedEvent 容器已经完成 refresh 动作后所触发的事件
ApplicationReadyEvent 容器已经运行中的事件
ApplicationFailedEvent 容器初始化失败所触发的事件
ApplicationStartingEvent 容器开始时所触发的事件
它们之间的触发顺序如下:
ApplicationStartingEvent ->ApplicationEnvironmentPreparedEvent -> ApplicationPreparedEvent ->ContextStartedEvent -> ContextRefreshedEvent ->ApplicationStartedEvent->ApplicationReadyEvent
2. 传播者
这里介绍关键的接口 ApplicationEventMulticaster,如类图关系如下:
ApplicationEventMulticaster 暴露了对监听器的添加删除,以及传播事件接口;为了更快获取对应的事件的监听器,添加一个缓存;为了避免并发问题,添加锁机制;有关监听器的添加删除,都是对 defaultRetriever 进行操作;
在 SimpleApplicationEventMulticaster 类中有两个属性,taskExecutor 是线程池对象,意味着监听器可以异步去处理事件;ErrorHandler 监听器处理事件异常时会有该接口对应的实现类进行处理。
然而这个 ApplicationEventMulticaster 是 spring 的内部实现逻辑。对外的提供的接口为 ApplicationEventPublisher,其暴露的接口如下:
从上面的类图来看,我们可以调用 ApplicationContext 的实现类对象,就可以发布事件;
那么,我们是如何拿到这个 ApplicationContext 对象的呢?
我们向 BeanFactory 注入 Bean,该 Bean 实现 ApplicationEventPublisherAware 该接口,BeanFactory 就会自动注入 ApplicationContext 对象到 Bean 对象中去;
3. 监听器
applicationListener 接口的类图如下:
我们只要找对应的对应的实现类,查阅里面的逻辑即可;这里不在对其的实现类进行介绍;
我们更加的关心的监听器是如何添加到上下文中去的;
方式一: 可以通过 ApplicationContext 上下文进行添加
方式二: 从 BeanFactory 容器中找出 ApplicationListener 类型的对象;
值得说的是:我们可以通过 @EventListener 注解,可以注入;其原理是由 EventListenerMethodProcessor 去检测 BeanFactory 容器中标有该注解的方法,将其方法通过 EventListenerFactory 接口的默认实现类 DefaultEventListenerFactory 来封装为 ApplicationListenerMethodAdapter 对象;另外也有事务的监听器 TransactionalEventListener,具体可以查阅深入理解 spring 框架之事务管理
四. spring Boot 事件机制
为什么单独抽出来呢,因为其是不归 spring 的上下文进行管控的,而是有 SpringApplication 进行管控的;
添加监听器是通过 spring.factories 配置文件进行添加默认的监听器
代码如下:
事件发布者 SpringApplicationRunListener 接口默认的实现类 EventPublishingRunListener,也是通过 spring.factories 配置文件进行配置,类图如下;
代码如下:
五. 总结
经过上述的初略的介绍,对 spring 的事件机制原理以及如何使用有了大体了介绍,以及 spring 初始化过程中所触发的事件都有哪些有了大体的介绍;所以,在业务代码方面,可以有效的运用该机制,进行代码的解耦,而不用创建轮子实现一套事件机制。
版权声明: 本文为 InfoQ 作者【邱学喆】的原创文章。
原文链接:【http://xie.infoq.cn/article/89dbe44f02f45d9d7bbe55ab5】。文章转载请联系作者。
评论