分类: java
2022-11-28 16:37:43
作者:王子源
指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
在观察者模式中,有以下几个角色。
主题也叫被观察者(subject):
观察者(observer):
观察者接受到消息后,即进行更新操作,对接收到的信息进行处理。
具体的被观察者(concretesubject):
定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。
具体的观察者(concreteobserver):
具体的观察者,每个观察者接收到消息后的处理反应是不同的,每个观察者都有自己的处理逻辑。
spring事件机制是观察者模式的实现。applicationcontext中事件处理是由applicationevent类和applicationlistener接口来提供的。如果一个bean实现了applicationlistener接口,并且已经发布到容器中去,每次applicationcontext发布一个applicationevent事件,这个bean就会接到通知。applicationevent 事件的发布需要显示触发,要么 spring 触发,要么我们编码触发。spring内置事件由spring触发。我们先来看一下,如何自定义spring事件,并使其被监听和发布。
2.1.1 事件
事件,applicationevent,该抽象类继承了eventobject,eventobject是jdk中的类,并建议所有的事件都应该继承自eventobject。
2.1.2 监听器
applicationlistener,是一个接口,该接口继承了eventlistener接口。eventlistener接口是jdk中的,建议所有的事件监听器都应该继承eventlistener。
2.1.3 事件发布器
applicationeventpublisher,applicationcontext继承了该接口,在applicationcontext的抽象实现类abstractapplicationcontext中做了实现下面我们来看一下
org.springframework.context.support.abstractapplicationcontext#publishevent(java.lang.object, org.springframework.core.resolvabletype)
我们可以看到,abstractapplicationcontext中publishevent方法{banned}最佳终执行发布事件的是applicationeventmulticaster#multicastevent方法,下面我们再来一起看一下multicastevent方法
上面介绍了非spring内置的事件发布和监听执行流程。总结一下
上面我们讲到了spring事件的发布,那么spring事件发布之后,spring是如何根据事件找到事件对应的监听器呢?我们一起来探究一下。
spring的容器初始化过程想必大家都已十分了解,这里就不过多赘述,我们直接看refresh方法在refresh方法中,有这样两个方法,initapplicationeventmulticaster()和registerlisteners()
我们先来看initapplicationeventmulticaster()方法
2.2.1 initapplicationeventmulticaster()
org.springframework.context.support.abstractapplicationcontext#initapplicationeventmulticaster
上述代码我们可以看出,spring先从beanfactory中获取applicationeventmulticaster如果为空,则直接创建simpleapplicationeventmulticaster
2.2.2 registerlisteners()
org.springframework.context.support.abstractapplicationcontext#registerlisteners
registerlisteners 是将各种实现了 applicationlistener 的监听器注册到 applicationeventmulticaster 事件广播器中
这里解释一下earlyapplicationlisteners
earlyapplicationlisteners的本质还是applicationlistener。spring单例ban的实例化是在refresh阶段实例化的,那么用户自定义的一些applicationlistener组件自然也是在这个阶段才初始化,但是spring容器启动过程中,在refresh完成之前还有很多事件:如spring上下文环境准备等事件,这些事件又是spring容器启动必须要监听的。所以spring定义了一个earlyapplicationlisteners集合,这个集合中的listener在factories文件中定义好,在容器refresh之前预先实例化好,然后就可以监听spring容器启动过程中的所有事件。
当registerlisteners方法执行完成,我们的监听器已经添加到多播器simpleapplicationeventmulticaster中了,并且earlyevent 早期事件也已经执行完毕。但是我们发现,如果自定义了一个监听器去监听spring内置的事件,此时并没有被执行,那我们注册的监听器是如何被执行的呢?答案在finishrefresh方法中。
2.2.3 finishrefresh
org.springframework.context.support.abstractapplicationcontext#finishrefresh
如果我们想要实现在spring容器中所有bean创建完成后做一些扩展功能,我们就可以实现applicationlistener这样我们就可以实现其功能了。至此,spring中同步的事件监听发布模式我们就讲解完了,当然spring还支持异步的消息监听执行机制。
2.2.4 spring中异步的监听执行机制
我们回过头来看一下applicationeventmulticaster#pushevent方法
{banned}最佳终执行发布事件的是applicationeventmulticaster#multicastevent方法,下面我们再来一起看一下multicastevent方法
可以看到,异步事件通知主要依靠simpleapplicationeventmulticaster 类中的executor去实现的,如果这个变量不配置的话默认事件通知是同步的, 否则就是异步通知了,要实现同时支持同步通知和异步通知就得从这里下手;我们上文已经分析过了在initapplicationeventmulticaster方法中有这样一段代码
如果beanfactory中已经有了simpleapplicationeventmulticaster则不会重新创建,那么我们可以再spring中注册一个simpleapplicationeventmulticaster并且向其中注入对应的executor这样我们就可以得到一个异步执行监听的simpleapplicationeventmulticaster了,我们的通知就会通过executor异步执行。这样可以大大提高事件发布的效率。
在springboot项目中我们可以增加一个配置类来实现
spring项目中我们也可以增加如下xml配置
本文主要讲解了观察者模式在spring中的应用及事件监听机制,jdk 也有实现提供事件监听机制spring 的事件机制也是基于jdk 来扩展的。spring 的事件机制默认是同步阻塞的,想要提升对应的效率要考虑异步事件。