Spring监听器

前置通俗铺垫 :Spring监听器是Spring框架内置的事件驱动模型 ,底层基于经典观察者模式设计,是Spring实现业务解耦、无侵入拓展、生命周期联动的核心机制。我们日常使用的SpringBoot启动事件、容器刷新事件、事务回调事件,全部依赖该机制实现。

一、核心底层原理:观察者模式落地

1.1 设计模式溯源

Spring监听器底层严格遵循观察者模式:定义一对多的依赖关系,当一个对象(事件源)状态发生改变时,所有依赖它的对象(监听器)会自动收到通知并执行对应逻辑。

传统硬编码业务耦合严重,新增逻辑需要修改原有代码;而Spring事件机制通过事件发布+监听器监听 的方式,实现发布者与订阅者完全解耦,符合开闭原则。

1.2 四大核心角色

Spring事件监听机制由四大核心组件构成,缺一不可,完整链路:事件源 → 事件 → 事件广播器 → 监听器

  • 事件源(Source):事件的发起者,也就是触发事件的源头,Spring容器本身就是最大的事件源,容器刷新、启动、关闭都会触发对应事件,也可自定义业务事件源。

  • 事件(ApplicationEvent):承载事件信息的载体,用于封装事件源、事件时间、自定义业务数据,所有Spring事件都必须继承该父类。

  • 事件广播器(ApplicationEventMulticaster) :核心调度中心,负责注册监听器、匹配事件、广播分发事件、调度执行监听器逻辑,是整个机制的中枢。

  • 监听器(ApplicationListener):事件订阅者,监听指定类型的事件,事件发布后自动触发执行自定义业务逻辑。

二、四大核心组件源码逐解

2.1 事件载体:ApplicationEvent(事件父类)

所有Spring内置事件、自定义业务事件的顶级父类,继承自Java原生事件体系,封装事件基础信息。

核心源码

复制代码
public abstract class ApplicationEvent extends EventObject {
    // 事件触发时间戳
    private final long timestamp;

    // 构造方法:必须传入事件源
    public ApplicationEvent(Object source) {
        super(source);
        this.timestamp = System.currentTimeMillis();
    }

    public final long getTimestamp() {
        return this.timestamp;
    }
}

核心说明 :抽象类,无法直接实例化,必须由自定义事件或框架内置事件继承;所有事件都会自带事件源触发时间两个基础属性。

2.2 监听器接口:ApplicationListener(原生接口)

Spring标准监听器接口,函数式接口,是Spring事件监听的顶层规范,泛型用于指定监听的事件类型。

核心源码

复制代码
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    // 事件触发核心方法:匹配事件后自动执行
    void onApplicationEvent(E event);
}

核心特性

  • 函数式接口,支持Lambda简化开发;

  • 泛型限定监听事件类型,实现精准匹配,不会监听无关事件;

  • 唯一核心方法onApplicationEvent,事件广播后自动回调。

2.3 事件广播器:ApplicationEventMulticaster(核心调度器)

事件广播器顶层接口,定义事件注册、事件广播、监听器管理的核心规范,Spring提供唯一默认实现:SimpleApplicationEventMulticaster

顶层接口核心方法

复制代码
public interface ApplicationEventMulticaster {
    // 添加监听器
    void addApplicationListener(ApplicationListener<?> listener);
    // 移除监听器
    void removeApplicationListener(ApplicationListener<?> listener);
    // 广播事件(核心方法)
    void multicastEvent(ApplicationEvent event);
}

2.4 事件发布入口:ApplicationContext

Spring上下文容器顶层接口,继承ApplicationEventPublisher,提供事件发布统一入口,开发者可直接通过容器发布自定义事件。

发布事件核心方法

复制代码
public interface ApplicationEventPublisher {
    // 发布事件对外入口
    void publishEvent(ApplicationEvent event);
}

三、Spring两种监听器实现方式(实战必备)

3.1 方式一:原生接口实现(ApplicationListener)

通过实现ApplicationListener接口,重写监听方法,适合固定事件监听、统一管理的场景。

实战代码示例

复制代码
// 自定义监听器,监听容器刷新完成事件
@Component
public class CustomListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println("容器刷新完成,执行自定义初始化逻辑");
    }
}

3.2 方式二:注解实现(@EventListener)【主流】

Spring3.0+推出的注解式监听,无需实现接口,简洁灵活,支持多事件监听、条件过滤,是项目开发主流用法。

实战代码示例

复制代码
@Component
public class AnnotationListener {

    // 监听容器刷新事件
    @EventListener(ContextRefreshedEvent.class)
    public void listenRefreshEvent() {
        System.out.println("注解监听:容器刷新完成");
    }

    // 监听自定义事件
    @EventListener(CustomBusinessEvent.class)
    public void listenCustomEvent(CustomBusinessEvent event) {
        System.out.println("接收自定义事件:" + event.getMsg());
    }
}

3.3 自定义事件完整实战(端到端)

完整实现:自定义事件 → 事件发布 → 监听器监听,完成业务解耦。

步骤1:自定义业务事件

复制代码
// 自定义业务事件,继承ApplicationEvent
public class CustomBusinessEvent extends ApplicationEvent {
    private String msg;

    public CustomBusinessEvent(Object source, String msg) {
        super(source);
        this.msg = msg;
    }

    // getter/setter
    public String getMsg() {
        return msg;
    }
}

步骤2:发布事件(业务层)

复制代码
@Service
public class BusinessService {
    @Autowired
    private ApplicationEventPublisher publisher;

    public void doBusiness() {
        // 业务逻辑
        System.out.println("执行核心业务逻辑");
        // 发布自定义事件
        publisher.publishEvent(new CustomBusinessEvent(this, "业务执行完成"));
    }
}

步骤3:监听事件

复制代码
@Component
public class CustomBusinessListener {
    @EventListener
    public void handleEvent(CustomBusinessEvent event) {
        System.out.println("监听器接收事件:" + event.getMsg());
        // 执行拓展业务:日志记录、消息推送、数据统计等
    }
}

四、核心源码完整执行链路(从启动到事件触发)

Spring监听器的核心生命周期:广播器初始化 → 监听器注册 → 事件发布 → 事件匹配 → 监听器执行,逐步骤拆解源码。

4.1 第一步:容器刷新初始化事件广播器

容器启动刷新阶段(refresh()),会优先初始化ApplicationEventMulticaster事件广播器,源码位于AbstractApplicationContext#initApplicationEventMulticaster

核心源码

复制代码
protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 优先从容器中获取自定义广播器(beanName固定:applicationEventMulticaster)
    if (beanFactory.containsBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
    } else {
        // 无自定义则创建默认广播器 SimpleApplicationEventMulticaster
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        // 注册为单例Bean
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
    }
}

核心结论:开发者可自定义同名Bean替换默认广播器,实现异步、自定义调度逻辑。

4.2 第二步:批量注册所有监听器

广播器初始化完成后,容器扫描所有ApplicationListener类型的Bean,批量注册到广播器中,源码位于AbstractApplicationContext#registerListeners

复制代码
protected void registerListeners() {
    // 注册硬编码注册的监听器
    for (ApplicationListener<?> listener : this.applicationListeners) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // 从容器中扫描所有ApplicationListener类型的Bean并注册
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }
}

核心说明:注解式监听器会被Spring后置处理器解析,自动封装为监听器对象注册到广播器。

4.3 第三步:事件发布入口源码

调用publishEvent发布事件,底层委托事件广播器执行广播逻辑。

复制代码
@Override
public void publishEvent(ApplicationEvent event) {
    // 核心:调用广播器的事件广播方法
    getApplicationEventMulticaster().multicastEvent(event);
}

4.4 第四步:核心------事件广播与监听器匹配执行

默认广播器SimpleApplicationEventMulticaster#multicastEvent是整个机制的核心,完成事件类型解析、监听器匹配、方法回调执行

复制代码
@Override
public void multicastEvent(ApplicationEvent event) {
    multicastEvent(event, resolveDefaultEventType(event));
}

protected void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    // 获取所有匹配当前事件类型的监听器
    Collection<ApplicationListener<?>> listeners = getApplicationListeners(event, type);
    // 遍历执行所有匹配的监听器
    for (ApplicationListener<?> listener : listeners) {
        invokeListener(listener, event);
    }
}

// 执行监听器核心方法
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
    try {
        // 回调监听器的onApplicationEvent方法
        listener.onApplicationEvent(event);
    } catch (Throwable ex) {
        // 异常兜底处理
        handleListenerError(ex, listener, event);
    }
}

五、同步&异步监听器机制(生产核心)

5.1 默认同步机制

Spring监听器默认同步执行:发布事件后,会阻塞当前线程,依次执行所有匹配的监听器,所有监听器执行完毕后,发布方法才会返回。

特点:执行有序、可保证事务一致性;缺点是阻塞主线程,高并发场景影响性能。

5.2 异步监听器实现(@Async)

生产中耗时操作(日志、推送、统计)需异步执行,Spring支持通过@Async快速实现异步监听。

实现步骤

  1. 启动类开启异步注解:@EnableAsync

  2. 监听器方法添加@Async

    @Component
    public class AsyncListener {
    @Async
    @EventListener(CustomBusinessEvent.class)
    public void asyncListen() {
    // 耗时业务,异步执行,不阻塞主线程
    }
    }

5.3 全局异步广播器(进阶)

自定义全局事件广播器,统一开启异步线程池,所有监听器默认异步执行。

复制代码
@Bean("applicationEventMulticaster")
public ApplicationEventMulticaster applicationEventMulticaster() {
    SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
    // 配置自定义线程池
    multicaster.setTaskExecutor(new ThreadPoolTaskExecutor());
    // 异步执行异常不影响主线程
    multicaster.setErrorHandler(new SimpleErrorHandler());
    return multicaster;
}

六、监听器执行顺序与优先级

多个监听器监听同一个事件时,可通过@Order注解指定执行优先级:数值越小,优先级越高,越先执行

复制代码
@Component
@Order(1) // 优先级最高
public class FirstListener implements ApplicationListener<CustomBusinessEvent> {
    @Override
    public void onApplicationEvent(CustomBusinessEvent event) {}
}

@Component
@Order(2)
public class SecondListener implements ApplicationListener<CustomBusinessEvent> {
    @Override
    public void onApplicationEvent(CustomBusinessEvent event) {}
}

特殊备注:该文中的示例代码为源代码整理后抽取部分核心点的代码作为理解展示,非真实源码,要看源码请自行根据方法名 / 类名前往对应的源码文件查看

七、Spring内置常用事件

Spring容器内置多个生命周期事件,覆盖容器全流程,可直接监听拓展:

  • ContextRefreshedEvent:容器刷新完成、所有Bean加载完毕触发;

  • ContextStartedEvent:容器启动完成触发;

  • ContextClosedEvent:容器关闭触发;

  • ApplicationReadyEvent:SpringBoot项目完全就绪,可接收流量;

  • ApplicationFailedEvent:项目启动失败触发。

八、生产应用场景与踩坑总结

8.1 核心应用场景

  • 业务解耦:核心业务与日志、推送、统计、缓存更新等拓展逻辑分离;

  • 容器生命周期拓展:容器启动后初始化数据、加载配置、注册服务;

  • 事务后置处理:事务提交成功后执行消息发送、数据同步;

  • 多级业务联动:一个业务动作触发多个无关联拓展操作。

8.2 生产踩坑点

  • 默认同步执行,耗时逻辑未加异步会阻塞主线程,导致接口超时、启动缓慢;

  • 未设置优先级,多监听器执行顺序不可控,导致业务异常;

  • 监听器抛出异常,会中断后续所有监听器执行(异步可规避);

  • 容器未完全刷新完成时发布事件,会出现Bean未加载空指针问题。

九、全文核心总结

  1. 底层原理 :Spring监听器基于观察者模式,四大核心角色:事件源、事件、广播器、监听器,实现发布订阅解耦;

  2. 两种实现 :原生ApplicationListener接口、注解@EventListener(主流);

  3. 源码核心链路:容器刷新初始化广播器 → 扫描注册所有监听器 → 发布事件 → 广播器匹配事件 → 回调监听器执行;

  4. 执行机制 :默认同步阻塞,支持@Async异步执行,通过@Order控制优先级;

  5. 核心价值:彻底解耦业务代码,无侵入拓展Spring生命周期与业务逻辑,是Spring生态拓展的核心底层机制。

相关推荐
逝水无殇1 小时前
C# 特性详解
开发语言·后端·c#
cfm_29141 小时前
SpringBoot 数据库全栈整合
数据库·spring boot·后端
xn71331 小时前
别再把 MCP Roots 当安全沙箱:一个符号链接就能逃逸目录
人工智能·后端·mcp
SamDeepThinking1 小时前
Java面向对象在JVM里怎么实现
java·后端·面试
学以智用1 小时前
HTTP 请求头 Headers 完整详解
前端·后端
妙码生花1 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(三十五):控制台静态页面、深入研究时间格式化方案
后端·go·ai编程
程序猿大帅1 小时前
Java 虚拟线程发布两年后,我们把它从生产环境移除了
后端
咸鱼翻身小阿橙2 小时前
多线程解析
java·开发语言
一枚码农出身的猎头2 小时前
岗位招聘:架构师,base湖南长沙,70-80w
java·架构