Spring Event 基于发布-订阅模式(观察者模式),使得系统中不同模块可以通过事件进行松散耦合的通信,而不需要直接依赖彼此,使用Spring Event,可以轻松实现业务解耦。
观察者模式
观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,使得一个对象(被观察者,Subject)可以通知多个观察者(Observers)对象,在其状态发生变化时,所有依赖它的对象都会收到通知并自动更新。
观察者模式中有四个角色(一般情况):目标、具体目标、观察者、具体观察者。在JDK中使用Observer接口和Observable类来作为观察者模式的抽象层,再自定义具体观察者类和具体观察目标类,可以方便地应用观察者模式。
Spring Event
为什么前面要简单的回顾了观察者模式呢?
事实上,Spring Event 是观察者模式的一种具体实现。Spring Event 机制的设计围绕三个核心组件展开:事件(Event)、事件发布者(Publisher)和事件监听器(Listener)。
具体实现
- 事件(Event)
@Getter
public class TypeComputationEvent extends ApplicationEvent {
String orderNo;
String status;
public TypeComputationEvent(Object source,String orderNo,String status) {
super(source);
this.orderNo = orderNo;
this.status = status;
}
}
事件是系统中某个动作或状态改变的标识,在 Spring 中,事件通常是一个继承自 ApplicationEvent
的类。
- 事件发布者(Publisher)
applicationEventPublisher.publishEvent(new TypeComputationEvent(this,"orderNo","status"))
事件发布者是触发事件的组件,在 Spring 中,任何组件都可以充当事件发布者,只需要通过依赖注入的方式获取 ApplicationEventPublisher
的实例,然后调用其 publishEvent()
方法发布事件。
- 事件监听器(Listener)
@Slf4j
@Component
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class TypeComputationListener {
@EventListener
public void onApplicationEvent(TypeComputationEvent event) {
log.info("=====>>>订单状态变更事件,订单号:{}", event.getOrderNo());
}
}
事件监听器用于当事件发布后,所有监听该事件的监听器都会被触发并执行相应的处理逻辑。Spring 提供了 @EventListener
注解,只需将其标注在方法上,该方法就会在相应事件发生时自动执行。@TransactionalEventListener
注解 通过与 Spring 的事务管理器集成,使得事件处理与事务的生命周期紧密相关。具体来说,它允许你指定在事务提交前或后处理事件。
默认情况下,ApplicationListener处理事件是同步执行的,在某些情况下,事件处理逻辑可能会比较耗时,为了避免阻塞主线程,可以通过 @Async
注解将事件处理逻辑异步化。
@Slf4j
@Component
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class TypeComputationListener {
@EventListener
@Async
public void onApplicationEvent(TypeComputationEvent event) {
log.info("=====>>>订单状态变更事件,订单号:{}", event.getOrderNo());
}
}
实现原理
Spring 的事件处理机制涉及到 ApplicationEventMulticaster
组件,这个组件是事件发布和监听的核心部分。
- ApplicationEventMulticaster 初始化,在 Spring 容器初始化过程中被创建。
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 如果手动新建了一个ApplicationEventMulticaster类型为的bean,则将这个bean作为事件广播器
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
// 否则,新建一个SimpleApplicationEventMulticaster作为默认的事件广播器
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
registerListeners
注册监听器,在 Spring 容器初始化过程中被创建。
protected void registerListeners() {
// 把监听器添加到监听器容器中
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 获取类型是ApplicationListener的beanName集合
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
Spring 容器在启动时会扫描所有的 @EventListener
注解或实现了 ApplicationListener
接口的类,并将这些监听器注册到 ApplicationEventMulticaster
中。
multicastEvent
发布事件
当我们通过applicationEventPublisher.publishEvent()
发布事件时,会调用 ApplicationEventMulticaster.multicastEvent()
方法,会将事件传递给所有匹配的监听器。
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);
}
}
}
总结
Spring Event 通过 Spring 容器初始化时创建并配置 ApplicationEventMulticaster 实例,扫描并注册所有事件监听器(通过注解或接口实现)。最后通过调用 multicastEvent() 方法,将事件广播给所有注册的监听器。Spring Event 它基于观察者模式实现,通过事件驱动的方式实现了模块间的松散耦合。
转载来源:https://juejin.cn/post/7402435366647119881