前言
Spring中提供了一套默认的事件监听机制,在容器初始化时便使用了这套机制。同时,Spring也提供了事件监听机制的接口扩展能力,开发者基于此可快速实现自定义的事件监听功能。
Spring的事件监听机制是在JDK事件监听的基础上进行的扩展,也是在典型观察者模式上的进一步抽象和改进。所以,结合Spring的事件监听机制与观察者模式来学习,可以达到理论与实践的完美融合。
本篇文章就以观察者模式和Spring事件监听机制作为切入点,结合具体的实例来对两者进行系统的学习和实践。
观察者模式
观察者模式(Observer Pattern),也叫作发布-订阅模式(Publish/Subscribe)。
无论是观察者模式,还是Spring的事件监听机制,本质上都是在定义对象间一对多的依赖关系,使得每当一个对象(被观察者/事件)改变状态时,所有依赖于它的对象(观察者/事件监听器)都会得到通知,并被自动更新。
观察者模式的优点在于:观察者和被观察者之间是抽象耦合,不管是新增观察者或是被观察者,都非常容易扩展。这也符合面向对象所倡导的“开闭原则”:对扩展开放,对修改关闭。
观察者模式适用于以下三类场景:
-
关联行为场景,而且关联是可拆分的。
-
事件多级触发场景。
-
跨系统的消息交换场景,比如消息队列的处理机制。
在使用的过程中,也要综合考虑开发效率和运行效率的问题。通常,一个被观察者会对应多个观察者,那么在开发和调试的过程中会有一定的复杂度。
同时,因为被观察者存在关联、多级拆分,也就是会有多个观察者,而Java消息的通知(和Spring的事件监听机制)默认是顺序执行的,如果其中一个观察者执行时间过长或卡死,势必会影响整体的效率。此时,就需要考虑异步处理。
观察者的角色定义
观察者模式是一个典型的发布-订阅模型,其中主要涉及四个角色:
-
抽象被观察者角色:内部持有所有观察者角色的引用,并对外提供新增、移除观察者角色、通知所有观察者的功能;
-
具体被观察者角色:当状态变更时,会通知到所有的观察者角色;
-
抽象观察者角色:抽象具体观察者角色的一些共性方法,如状态变更方法;
-
具体观察者角色:实现抽象观察者角色的方法;
UML类图展示类观察者模式大体如下:
观察者模式类图
以具体的代码来展示一下观察者模式的实现。
第一,定义抽象观察者。
/**
* 抽象观察者角色
* @author sec
**/
public abstract class AbstractObserver {
/**
* 接收消息
* @param context 消息内容
*/
public abstract void receiveMsg(String context);
}
第二,定义抽象被观察者。
/**
* 抽象主题(抽象被观察者角色)
* @author sec
**/
public abstract class AbstractSubject {
/**
* 持有所有抽象观察者角色的集合引用
*/
private final List<AbstractObserver> observers = new ArrayList<>();
/**
* 添加一个观察者
* @param observer 观察者
*/
public void addObserver(AbstractObserver observer){
observers.add(observer);
}
/**
* 移除一个观察者
* @param observer 观察者
*/
public void removeObserver(AbstractObserver observer){
observers.remove(observer);
}
/**
* 通知所有的观察者,执行观察者更新方法
* @param context 通知内容
*/
public void notifyObserver(String context){
observers.forEach(observer -> observer.receiveMsg(context));
}
}
第三,定义具体被观察者,实现了抽象被观察者。
/**
* 具体被观察者
* @author sec
**/
public class ConcreteSubj