乐于分享
好东西不私藏

第九篇・Spring 5 源码深度拆解:Spring 事件驱动模型

第九篇・Spring 5 源码深度拆解:Spring 事件驱动模型

👋 前言

前面我们已经叨叨完:IOC、生命周期、循环依赖、AOP、事务、SpringMVC、Boot 自动配置、资源加载与 Environment。

Spring 内部也存在靠事件驱动解耦的:容器启动、刷新、容器刷新(refresh)完成后发布 ContextRefreshedEvent,此时所有 Bean 均已初始化完毕,是最常用的启动后逻辑入口……这一篇我们梳理事件模型,了解掌握 Spring 轻量但极其重要的扩展机制。

即刻起简单又轻松。

一、核心角色

  1. ApplicationEvent:事件本身(所有事件的父类)
  2. ApplicationListener:事件监听器(观察者)
  3. ApplicationEventPublisher:事件发布器(被观察者)
  4. ApplicationContext:本身就是发布器,内部维护监听器
  5. ApplicationEventMulticaster:Spring 通过 AbstractApplicationContext.initApplicationEventMulticaster() 方法初始化事件多播器。默认创建的是 SimpleApplicationEventMulticaster 实例;同时还承担了事件匹配和路由的重要职责——它需要根据事件类型找到对应的监听器进行派发

二、最简流程

  1. 定义事件 
    1. extends ApplicationEvent  经典方式
    2. 直接使用任意pojo
  1. 定义监听器 implements ApplicationListener
  2. 容器启动时收集所有监听器
  3. 调用 publishEvent 发布
  4. Spring 遍历匹配监听器执行 onApplicationEvent

三、Spring 内置核心事件

  • ContextRefreshedEvent:容器完全刷新完成(Bean 都初始化好了)
  • ContextStartedEvent:容器启动
  • ContextStoppedEvent:容器停止
  • ContextClosedEvent:容器关闭(单例 Bean 销毁前)
  • RequestHandledEvent:SpringMVC 请求处理完成

最常用:ContextRefreshedEvent很多框架启动逻辑都监听它。

四、源码级流程:事件是怎么被发布和消费的?

核心调用链

// 1. 发布入口publishEvent(Object event    ↓// 2. 获取事件类型,包装为 ApplicationEvent(若 event 本身不是)getApplicationEventMulticaster()     ↓// 3. 多播器开始派发multicastEvent(ApplicationEvent event, ResolvableType eventType)    ↓// 4. 获取所有匹配的监听器getApplicationListeners(event, type)    ↓// 5. 遍历监听器,逐个调用invokeListener(listener, event)    ↓// 6. 最终执行监听器的回调listener.onApplicationEvent(event)

1. 发布入口:publishEvent

几乎所有地方最终都会走到:

// AbstractApplicationContextprotectedvoidpublishEvent(Object event, @Nullable ResolvableType typeHint) {    // 1. 包装成 ApplicationEvent    ApplicationEvent applicationEvent = null;    if (event instanceof ApplicationEvent) {        applicationEvent = (ApplicationEvent) event;    } else {        applicationEvent = new PayloadApplicationEvent<>(thisevent);    }    // 2. 获取多播器    ApplicationEventMulticaster multicaster = this.applicationEventMulticaster;    // 3. 多播事件:发给所有匹配监听器    multicaster.multicastEvent(applicationEvent, typeHint);}

2. 事件多播核心:SimpleApplicationEventMulticaster

@OverridepublicvoidmulticastEvent(ApplicationEvent event, @Nullable ResolvableType typeHint) {    ResolvableType eventType = (typeHint != null ? typeHint : resolveDefaultEventType(event));    Executor executor = getTaskExecutor();    for (ApplicationListener<?> listener : getApplicationListeners(event, eventType)) {        if (executor != null) {            executor.execute(() -> invokeListener(listener, event));        } else {            invokeListener(listener, event);        }    }}

3. 最终执行监听器

privatevoiddoInvokeListener(ApplicationListener listener, ApplicationEvent event) {    listener.onApplicationEvent(event);}

五、@EventListener 注解原理

1. 解析器:EventListenerMethodProcessor

EventListenerMethodProcessor 实现 SmartInitializingSingleton 接口,在容器所有单例 Bean 完成实例化、依赖注入、初始化之后,执行 afterSingletonsInstantiated()SmartInitializingSingleton.afterSingletonsInstantiated() 的触发时机是“所有单例 Bean 实例化完成之后的一次性回调;而实例化、依赖注入、初始化是bean生命周期中更早阶段发生的事情。

2. 核心流程

  1. 遍历所有单例 Bean
  2. 找出带 @EventListener 的方法
  3. 解析监听的事件类型
  4. 包装成 ApplicationListenerMethodAdapter
  5. 注册到 ApplicationEventMulticaster

3. 执行时

发布事件 → 匹配 adapter → 反射调用你写的 @EventListener 方法。

六、异步事件 @Async + 事件

Spring 事件默认是同步执行的(发布者线程阻塞直到所有监听器执行完毕)。

开启步骤

  1. 全局异步(所有事件都异步)

重写 applicationEventMulticaster Bean,为其设置 TaskExecutor

配置后,所有事件的派发都会提交到线程池中执行,发布者线程立即返回。

@Configurationpublic class AsyncEventConfig {    @Bean(name = "applicationEventMulticaster")    public ApplicationEventMulticaster applicationEventMulticaster() {        SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();        multicaster.setTaskExecutor(Executors.newFixedThreadPool(5));  // 设置线程池        return multicaster;    }}

  1. 局部异步启动类加 @EnableAsync
@EnableAsync   // 启动类或配置类上添加@SpringBootApplicationpublic classApplication{ ... }@Componentpublic classOrderEventListener{    @Async   // 仅此监听器异步执行    @EventListener    public void handleOrder(OrderEvent event) {        // 异步处理逻辑    }}

  1. 配置 TaskExecutor Bean (可选但强烈建议配置
  2. 监听方法上加 @Async

可自定义 TaskExecutor Bean 控制线程池,不配置则使用默认的 SimpleAsyncTaskExecutor(每个任务新建线程,不推荐生产环境使用)。

原理

多播时判断有 executor 就提交线程池,不阻塞主线程。

七、事务绑定事件 @TransactionalEventListener

核心:TransactionSynchronization

 若发布事件时不存在事务,默认直接执行,可通过 fallbackExecution 控制。

原理:

  1. 不立即执行监听方法
  2. 把执行逻辑挂到事务同步管理器
  3. 等事务 提交 / 回滚 / 完成 后再执行

常用阶段

  • BEFORE_COMMIT
  • AFTER_COMMIT
  • AFTER_ROLLBACK
  • AFTER_COMPLETION

这是微服务 / 分布式事务里非常实用的 “事务完成后再发消息” 方案。

八、Spring 事件完整总结

  1. 事件:ApplicationEvent
  2. 监听:ApplicationListener / @EventListener
  3. 发布:ApplicationContext.publishEvent
  4. 调度:ApplicationEventMulticaster
  5. 异步:@Async + TaskExecutor
  6. 事务绑定:@TransactionalEventListener
  7. 内置事件:启动 / 刷新 / 停止 / 关闭

轻量、解耦、无侵入,是 Spring 内部和业务扩展最常用的机制之一。

下篇预告

第十篇・Spring 5 源码深度拆解:Spring 类型转换与校验体系

  • Converter、ConversionService 类型转换
  • Formatter、PropertyEditor 传统绑定
  • @Valid、Validator 校验底层原理
  • SpringMVC 参数自动绑定核心逻辑
  • 自定义类型转换器实战补齐参数绑定、数据绑定最后一块拼图。