分类: 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 的事件机制默认是同步阻塞的,想要提升对应的效率要考虑异步事件。