一、基本介绍
Spring中的事件处理机制是对设计模式中的观察者模式的一种扩展。
在传统的观察者模式中,最主要的对象有观察者,被观察者,当被观察者的状态或行为发生改变时,所有的观察者将会收到通知,并作出相应的响应。比如当**红绿灯(被观察者)由红灯变为绿灯(被观察者状态改变)**状态时,驾驶员(观察者)会继续行驶汽车(观察者作出的响应)。
在Spring中,涉及到的对象主要有:事件监听器、事件源、事件、多播器;
二、Spring事件中涉及到的对象
事件
ApplicationEvent
对应于传统观察者模式中的被观察者状态或行为的改变,也就是每个状态或行为的改变都对应于一个事件。
事件源
事件源就是产生事件的对象,对应于传统观察者模式中的被观察者,用于生成事件对象。
事件监听器
ApplicationListener
事件监听器就是传统观察者模式中的观察者,当接收到事件时会根据事件类型的不同而做出不同的响应。
多播器
ApplicationEventMulticaster
可以理解为Spring中的事件管理中心,类似于广播站,向事件监听器广播事件信息,当事件源产生事件后,并不由事件源去一个个的通知事件监听器,而是由多播器向Spring中的所有事件监听器发送事件,这样做的好处就是每一个事件源不必再分别维护一个容器中所有事件监听器的列表,减少开销,且代码更加简洁(通知事件监听器的代码不必在每个事件源内重复编写)。
三、Spring容器启动过程中对事件的处理
下面是Spring容器启动过程中对事件的大致处理流程
public void refresh() throws BeansException, IllegalStateException {
// ......
// 初始化事件多播器
initApplicationEventMulticaster();
// ......
// 注册事件监听器
registerListeners();
// 这里会发布一个事件
finishRefresh();
}
初始化事件多播器
初始化流程:
存在就直接把多播器赋值给applicationEventMulticaster
,不存在就创建一个多播器,然后赋值给applicationEventMulticaster
。
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 已经存在多播器
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
// ......
}
else {
// 创建多播器对象
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
// ......
}
}
注册事件监听器
protected void registerListeners() {
// 下面两段代码都是向多播器中注册事件监听器
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 从BeanDefinition中获取事件监听器
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// ......
}
发布事件
主要流程:
- 获取事件类型
- 发布事件
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
// ......
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
// 获取事件的类型
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// ......
else {
// 发布事件
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
}
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
// 这里会根据事件类型过滤出需要对当前事件类型作出响应的事件监听器
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 每个事件监听器都会有一个onApplicationEvent方法,用于对事件作出响应,不同的事件监听器可以有自己的处理逻辑
listener.onApplicationEvent(event);
}
// ......
}
四、自定义事件事件监听器
注:这里只是简单实现,学到SpringBoot时继续补充。
自定义事件
自定义事件只需要自定义的类继承
ApplicationEvent
即可。
public class MyEvent extends ApplicationEvent implements Serializable {
private static final long serialVersionUID = 7099057108183571937L;
public MyEvent(Object source) {
super(source);
}
@Override
public String toString() {
return "MyEvent";
}
}
自定义事件监听器
自定义事件监听器只需要自定义的类实现
ApplicationListener
接口即可,同时可以指定接受的事件类型
// 只对MyEvent类型的事件作出响应
public class MyEventListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("MyEventListener 监听到事件" + event.toString());
}
}
自定义完事件监听器后,还需要将事件监听器注册到Spring
容器中:
<bean class="com.yk.event.MyEventListener"></bean>
这样在有了MyEvent
事件后,事件监听器MyEventListener
便会对其做出响应。