Spring源码分析之事件机制——观察者模式(一)
目录
事件基类定义
事件监听器接口
事件发布者接口及实现
事件广播器实现
小小总结
Spring源码分析之事件机制——观察者模式(一)-CSDN博客
Spring源码分析之事件机制——观察者模式(二)-CSDN博客
Spring源码分析之事件机制——观察者模式(三)-CSDN博客
这两篇文章是这个篇章的后篇,感兴趣的读者可以阅读一下,从spring源码分析观察者模式
事件基类定义
public abstract class ApplicationEvent extends EventObject {
// 事件发生的时间戳
private final long timestamp;
public ApplicationEvent(Object source) {
// source表示事件源,即发布事件的对象
super(source);
this.timestamp = System.currentTimeMillis();
}
// 获取事件发生时间
public final long getTimestamp() {
return this.timestamp;
}
}
ApplicationEvent作为所有Spring事件的基类,继承自Java的EventObject,通过记录时间戳和事件源,为事件提供了基本的元数据信息,使得事件能够携带更多的上下文信息。
事件监听器接口
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* 处理应用事件的方法
* @param event 要响应的事件
*/
void onApplicationEvent(E event);
}
ApplicationListener接口定义了事件监听器的标准,通过泛型约束限定了具体监听的事件类型,使得监听器能够只关注特定类型的事件,我觉得spring的这种设计既保证了类型安全,又提供了良好的扩展性。
事件发布者接口及实现
@FunctionalInterface
public interface ApplicationEventPublisher {
/**
* 发布事件的方法
* @param event 要发布的事件
*/
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
/**
* 发布任意对象作为事件
* @param event 要发布的事件对象
*/
void publishEvent(Object event);
}
public abstract class AbstractApplicationContext implements ApplicationEventPublisher {
// 事件广播器
private ApplicationEventMulticaster applicationEventMulticaster;
// 早期事件缓存,用于存储容器未完全初始化前的事件
private Set<ApplicationEvent> earlyApplicationEvents;
@Override
public void publishEvent(Object event) {
// 确保事件对象是ApplicationEvent类型
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
} else {
// 将普通对象包装为PayloadApplicationEvent
applicationEvent = new PayloadApplicationEvent<>(this, event);
}
// 如果容器还在初始化,则将事件添加到早期事件集合
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
} else {
// 通过事件广播器发布事件
getApplicationEventMulticaster().multicastEvent(applicationEvent);
}
// 如果存在父容器,则同时发布到父容器
if (this.parent != null) {
this.parent.publishEvent(event);
}
}
// 初始化事件广播器
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);
}
}
}
AbstractApplicationContext实现了事件发布的核心逻辑,通过事件广播器将事件分发给所有相关的监听器,同时处理了事件的向上传播和早期事件的缓存。
事件广播器实现
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
// 任务执行器,用于异步事件处理
@Nullable
private Executor taskExecutor;
// 错误处理器
@Nullable
private ErrorHandler errorHandler;
@Override
public void multicastEvent(ApplicationEvent event) {
// 解析事件类型并广播
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
// 解析事件类型
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
// 获取所有匹配的监听器并执行
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
// 异步执行
executor.execute(() -> invokeListener(listener, event));
} else {
// 同步执行
invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
} catch (Throwable err) {
errorHandler.handleError(err);
}
} else {
doInvokeListener(listener, event);
}
}
}
SimpleApplicationEventMulticaster提供了事件广播的具体实现,支持同步和异步两种事件处理方式,并提供了错误处理机制,通过这种设计,使得事件的处理更加灵活和可靠,同时也为性能优化提供了可能。
小小总结
Spring的事件机制通过这些精心设计的组件,构建了一个完整的观察者模式实现,它不仅支持Spring框架内部的事件处理,也为应用程序提供了一个强大的事件驱动架构基础,通过这种方式,可以实现组件间的松耦合通信,提高系统的可维护性和扩展性。整个实现考虑了性能、可靠性和易用性等多个方面,是一个非常典型的观察者模式应用案例。