【从零构建Spring|第十一节】 观察者模式实现容器事件及监听器
【从零构建Spring|第十一节】 观察者模式实现容器事件及监听器
Shio【从零构建Spring|第十一节】 观察者模式实现容器事件及监听器
Spring 为什么需要事件,可以用来干什么?
用来解耦代码。高内聚,低耦合的设计思想
可以用于处理日志监控和各种事件发布订阅的客制化定义
观察者模式
在开发中,有很多利用到解耦的场景,例如在注册事件完成后异步发送事件推送消息,用户下单后异步发送MQ消息给与用户后续业务的跟进情况,用户付完款后就可以发送货物派送进度,都是依靠事件订阅和发布以及MQ消息这样的组件,来处理系统之间的调用解耦,最终也通过解耦的方式来提升整体系统架构的稳定性和负载能力
其实解耦思想就是观察者模式的一种体现。当对象间存在一对多关系时,则适合使用观察者模式,它定义了对象之间的一种一对多依赖关系。当一个对象的状态改变时,所有依赖他,与他有关的对象都会得到通知并且自动更新。
观察者模式角色
Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
这一节中和前几节结合起来,才更能明白 Spring 框架,在 Spring 框架中,我感觉是万物即 Bean 对象
就像本节的事件监听器,就是通过 xml 文件配置,被 ClassPathXmlApplicationContext 面向用户的应用上下文读取出来并通过 bean 对象加载。在上一节中 FactoryBean 实际上也是通过 xml 配置,读取出来实例化成 bean。只不过这个 bean 我们创建的更加简单,不需要配置引用类型。
设计
事件
在观察者模式中,我们提到一个事件想要运作,需要 事件、事件广播器(事件监听器)、事件发布器 三大部分,事件广播器实际上是一个管理 事件监听器的容器,负责处理其添加、触发。在 AbstractApplicationContext 中,initApplicationEventMulticaster
和registerListeners
去实现事件监听器的注册添加,因为 Spring IoC 容器中万物皆 Bean,因此监听器是由单例模式注册的,之后将所有的监听器都交由广播器来统一管理。
private void initApplicationEventMulticaster() { |
事件机制的行为如下:
同时还有专门处理容器关闭和容器刷新的监听器 ContextCloseEventListener
、ContextRefreshEventListener
并且由于是事件机制,它也是异步的,当等到一个事件的发布,事件监听器才会被触发去执行相应逻辑,即调用onApplicationEvent
方法完成相关逻辑
具体情况如图,事件广播器接受到事件发布之后,调用内部广播方法,遍历通知所有被管理的监听器,监听器调用各自的执行方法。完成事件订阅与接收逻辑
工程
约定接口(整个事件机制的基石)
监听器接口
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { |
发布器接口
public interface ApplicationEventPublisher { |
- 只处理发布事件的逻辑
事件广播器
/** |
自定义事件的实现
事件监听器(刷新容器、关闭容器、自定义事件监听)的实现逻辑
AbstractApplicationContext 中集成了发布事件以及添加事件监听器的逻辑,并且提供了接口,这就是我们事件的入口
如何获取这个入口
- 像测试用例一样,直接用xml去获取ClassPathXmlApplicationContext
- 通过ApplicationContextAware
ApplicationContextAware
在 AbstractApplicationContext#refresh,会为实现了 ApplicationContextAware 的类设置好对应的 ApplicationContext,那就可以通过这样获取到入口。
而这个操作的实现,是注入了一个实现了BeanPostProcessor的专门用于添加ApplicationContext的实例ApplicationContextAwareProcessor
那么由此又可以引申出,对象创建,BeanFactoryPostProcessor,ApplicationContext,Bean的生命周期,毕竟这 些都是在Bean的生命周期里实现的。
通过这章又可以回想起Cglib方式创建的对象,那是源于当时最初没有对有参构造进行特殊设置,从而有cglib和普通的反射方法创建的不同策略。
spring的IOC所进行的就是对Bean进行管理,Bean就是一个个的实例化对象(Spring IoC 中万物即 Bean 对象。每个Bean从创建到销毁,中间他是有许许多多的过程,它就使用了 ApplicationContext 进而扩展,对每个环节进行控制和扩展方法。比如对象创建前后的操作,对象感知容器,复杂对象的创建可以用另一种 FactoryBean 的方法,对事件的控制等等
参考: