1.Spring Event简介
- Spring Event是设计模式中典型的——观察者模式。
- 定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于(观察)它的对象都会接收到通知,然后执行自身的业务。实现了业务间的松耦合。
- 观察者模式结构
被观察者:类中有一个存放观察者集合的容器。主要功能包含,向这个集合添加观察者,移除观察者,以及调用观察者。观察者:一般提供一个接口,在被观察者状态发生变化时触发。
- Spring Event核心结构即观察者模式的结构。
2.Spring Event主要类
- Spring Event主要类有三个:
- org.springframework.context.
ApplicationEvent:事件,被观察者发布了什么样的事件,观察者观察什么样的事件,根据业务继承此类来实现,用来区分不同的监听者。- ApplicationEvent继承JDK自带的
EventObject,EventObject为所有事件类的父类。
- ApplicationEvent继承JDK自带的
- org.springframework.context.
ApplicationEventPublisher:被观察者,通过这个类来实现对观察者的通知,告知(调用)观察者,我发布了这样的事件。 - org.springframework.context.
ApplicationListener:观察者,观察对应的事件,在被观察者发布对应事件时,触发void onApplicationEvent(E event)方法。- ApplicationListener 实现JDK自带的tag接口
EventListener,EventListener无任何接口方法,只用来标志这个类的实现类是一个事件监听类。
- ApplicationListener 实现JDK自带的tag接口
- org.springframework.context.
- PS:如果要自己实现观察者模式,也可以参考Spring Event的模式,只要自己在实现的发布工具(
等同于ApplicationEventPublisher)中,存储监听器的集合,然后在发布事件时,调用对应的监听器即可。 - 继承关系
- 实际应用中,被观察者通过类
ApplicationContext进行事件的发布

- 实际应用中,通过实现
ApplicationListener并指定监听的Event事件的实现观察者
- 实际应用中,被观察者通过类
3.源码分析
- 可能大家会疑惑,被观察者发布事件时,是怎样找到对应的监听器,并对其发起调用的呢?下面我们通过源码来分析。
- ApplicationContext——加载应用中的Spring监听器
- 通过下图,可以看到应用中ApplicationContext的实际实现是
GenericApplicationContext。

- GenericApplicationContext的继承关系

- 在GenericApplicationContext的继承关系中,核心类为:
AbstractApplicationContextAbstractApplicationContext提供了一个addApplicationListener的方法添加Spring容器中的所有ApplicationListener的实现。

- 可以看到Spring容器加载时会将容器中的ApplicationListener的实现类添加到集合中。那这个方法是怎样触发的呢?
- 向上查找具体的方法调用方,可以查找到类:
EventListenerMethodProcessor,该类实现的接口之一:SmartInitializingSingleton,该接口的作用是在单例 bean都初始化完成以后, 容器会回调该接口的方法afterSingletonsInstantiated,就是在此方法中ApplicationListener添加到了集合中。
- 向上查找具体的方法调用方,可以查找到类:
- 虽然上图显示是,添加监听器到AbstractApplicationContext维护的私有属
性集合applicationListeners中,但因为AbstractApplicationContext实现了接口ConfigurableApplicationContext在容器初始化完成后,会调用refresh方法,然后判断属性applicationEventMulticaster是否存在,不存在就新建一个,然后赋值给属性。这样后续ApplicationListener实现,都是添加到applicationEventMulticaster中。(没明白Spring这么做的原因?),因为在后面分析发布事件的时候,会发现最终进行发布的时候,还是会走ApplicationEventMulticaster的方法multicastEvent(多播)。

- 通过上面的分析我们可以知道应用中的Spring监听器是如何加载到集合的。下面我们看下事件的发布。
- ApplicationContext——发布事件
- 从逻辑上来说,事件发布就是通过
ApplicationContext的publishEvent方法,同步或异步的调用存储在集合中ApplicationListener实例。 - 具体代码实现:org.springframework.context.support.
AbstractApplicationContext#publishEvent(java.lang.Object, org.springframework.core.ResolvableType)
- 需要注意的是:我这里发布的事件,是在初始化加载的时候,添加到AbstractApplicationContext的私有属性
applicationListeners中的监听器,但是最终他还是使用了org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType)进行事件发布。(这就是让人比较奇怪的地方,如果有人知道为啥,麻烦留言告诉下)。
- 通过上图可以看到,在获取到所有监听此事件(Event)监听器之后,进行遍历调用监听器。其中,如果系统配置了统一的
任务调度器,就会使用配置的任务调度器异步调用,没有配置就会进行同步调用。 - 在invokeListener方法中,可以看到可以对指定的异常进行处理。只要配置了
ErrorHandler实现类。
- 从逻辑上来说,事件发布就是通过
- 通过下图,可以看到应用中ApplicationContext的实际实现是
到此Spring Event源码分析就结束了,对于文中提到的异步执行,可以百度搜索。文中有什么描述错误的地方,欢迎大家指出,有什么问题,也可以留言交流。
本文详细解析了Spring Event的源码,介绍了其作为观察者模式的应用。主要内容包括Spring Event的三大核心类:ApplicationEvent、ApplicationContext及ApplicationListener。在源码分析部分,阐述了ApplicationContext如何加载监听器,以及事件发布的具体流程。最后,讨论了事件发布的异步执行和异常处理机制。
1122

被折叠的 条评论
为什么被折叠?



