ApplicationListener 和 SpringApplicationRunListener 深度解析对比

在 Spring Boot 中,ApplicationListener 和 SpringApplicationRunListener 是两个作用层级、加载时机和使用场景都截然不同的监听器。

它们最核心的区别在于:‌

ApplicationListener 是 Spring 容器内的"业务事件监听器",

SpringApplicationRunListener 是 Spring Boot 启动流程的"生命周期监听器"。

核心区别概述

这两个接口服务于不同的阶段和目的:

  • ApplicationListener :关注的是 Spring 容器内部 发生的事件,主要用于业务逻辑通用服务在容器生命周期不同阶段(包括应用启动阶段,跟事件监听类型有关)的操作。
  • SpringApplicationRunListener :关注的是 Spring Boot 应用启动过程本身 的关键节点,主要用于框架层面基础设施 在容器初始化之前期间的操作。

详细对比

  1. 所属框架与作用域

    • ApplicationListener
      • 属于 Spring Framework
      • 作用域是整个 Spring 应用上下文(ApplicationContext)的生命周期。容器启动后,它可以监听容器内发布的各种事件。
    • SpringApplicationRunListener
      • 属于 Spring Boot
      • 作用域仅限于 SpringApplication.run(...) 方法的执行过程。它监听的是应用启动流程中的特定阶段。
  2. 加载时机与管理方式

    • ApplicationListener
      • 作为 Spring Bean 被管理。
      • 加载时机:在 Spring 容器启动过程中,随着其他 Bean 一起被创建和初始化。
      • 注册方式:可以通过 @Component@Bean 注解定义,或者通过 SpringApplication.addListeners(...) 方法添加。
      • 支持依赖注入 :可以像普通 Bean 一样使用 @Autowired@Value 等。
    • SpringApplicationRunListener
      • 不由 Spring 容器管理
      • 加载时机:非常早 ,在 Spring 容器创建之前
      • 注册方式:必须通过在 META-INF/spring.factories 文件中配置 org.springframework.boot.SpringApplicationRunListener 键来声明实现类的全限定名(使用 SPI 机制)。
      • 不支持依赖注入 :因为它加载时 Spring 容器还不存在,无法注入其他 Bean 或读取 @Value 配置。只能通过构造参数(接收 SpringApplication 实例和 String[] args)或直接访问环境等方式获取信息。
  3. 监听的事件类型

    • ApplicationListener

      • 监听 ApplicationEvent 及其子类
      • 事件来源广泛:
        • Spring 内置事件 :如 ContextRefreshedEvent(容器刷新完成)、ContextClosedEvent(容器关闭)。
        • Spring Boot 启动事件 :如 ApplicationStartedEventApplicationReadyEvent(注意:这些事件通常是由 EventPublishingRunListener 转发的 SpringApplicationRunListener 事件,即可以监听spring boot 的启动生命周期,使用形式ApplicationListener<ApplicationStartedEvent>)。
        • 自定义业务事件 :开发者可以定义自己的事件类(如 OrderPaidEvent)并发布。
        • 实现方式:使用@EventListener注解简化监听,或者实现 ApplicationListener<自定义事件>,在 onApplicationEvent 中编写处理逻辑。
    • SpringApplicationRunListener

      • 监听的是 Spring Boot 启动流程中的固定阶段 ,每个阶段对应接口中的一个方法回调:
        • startingrun() 方法刚开始执行。
        • environmentPreparedEnvironment 准备好,但 ApplicationContext 还未创建。
        • contextPreparedApplicationContext 创建好,但在加载 Bean 定义之前。
        • contextLoadedApplicationContext 加载完 Bean 定义,但在刷新容器之前。
        • startedApplicationContext 已刷新,应用已启动,但 CommandLineRunner/ApplicationRunner 还未执行。
        • running:所有 Runner 已执行完毕,run() 方法即将结束。
        • failed:启动过程中发生异常。
  4. 典型使用场景

    • ApplicationListener
      • 业务逻辑解耦 :监听自定义业务事件(如 UserRegisteredEvent),触发发送邮件、初始化用户信息等操作。
      • 容器生命周期钩子 :监听 ContextRefreshedEvent 进行缓存预热、初始化全局服务;监听 ApplicationReadyEvent 执行最终检查或通知外部系统应用已就绪。
      • 响应内置事件 :监听 ContextClosedEvent 执行资源清理。
    • SpringApplicationRunListener
      • 极早期配置处理 :在 environmentPrepared 阶段从远程配置中心(如 Nacos, Consul)拉取配置,或者对配置文件中的加密属性进行解密。
      • 启动过程定制 :在 starting 阶段输出自定义 Banner 或启动日志。
      • 环境检查与准备 :在 environmentPrepared 阶段验证环境变量或进行必要的系统设置。
      • 框架/工具集成 :在容器初始化前(如 contextPrepared 或更早)集成 APM 监控探针进行字节码增强。

两者联系

Spring Boot 提供了一个关键的 SpringApplicationRunListener 实现:EventPublishingRunListener。它的作用是将 SpringApplicationRunListener 接收到的各个阶段回调(如 starting, environmentPrepared)转换并发布 成对应的 ApplicationEvent (如 ApplicationStartingEvent, ApplicationEnvironmentPreparedEvent)。这些事件随后会被广播给所有注册的 ApplicationListener

因此,ApplicationListener 可以间接感知到 Spring Boot 的启动过程(通过监听 ApplicationStartingEvent, ApplicationEnvironmentPreparedEvent 等事件),而 SpringApplicationRunListener 提供了更底层、更早期的介入点。EventPublishingRunListener 充当了桥梁角色。

总结对比表

特性 ApplicationListener SpringApplicationRunListener
所属框架 Spring Framework Spring Boot
作用域 Spring 容器生命周期 SpringApplication.run() 执行过程
管理方式 Spring 容器管理的 Bean SPI 加载,不受容器管理
依赖注入支持 支持 (@Autowired, @Value) 不支持
注册方式 @Component, @Bean, addListeners() META-INF/spring.factories (SPI)
事件/阶段 ApplicationEvent 及其子类 启动流程的固定方法回调 (starting 等)
典型场景 业务解耦、缓存预热、处理自定义事件 启动前配置加载、解密、环境检查、APM 集成
执行时机 (相对容器) 容器初始化 容器初始化期间

理解这些区别有助于在合适的场景选择正确的扩展点。

相关推荐
麻瓜生活睁不开眼4 小时前
Android16修改全局桌面视图边框四直角显示为弧边圆角
android·java·深度学习
dear_bi_MyOnly4 小时前
【MyBatis 操作数据库】
java·数据库·学习·mybatis·学习方法
Wang's Blog4 小时前
Go-Zero 项目开发43:基于 Filebeat 收集各个服务的日志信息
开发语言·golang·go-zero·filebeat
2601_953720824 小时前
【计算机毕业设计】基于Spring Boot的心理健康咨询与评测系统的设计与实现
java·spring boot·后端
丈剑走天涯5 小时前
JDK 17 正式特性
java·开发语言
秋田君5 小时前
QT_QFontDialog类字体对话框
开发语言·qt
圣光SG6 小时前
Java操作题练习(七)
java·开发语言·算法
whyfail6 小时前
前端学 Spring Boot(8):接口为什么越用越慢?
前端·spring boot·后端
麻瓜老宋7 小时前
AI开发C语言应用按步走,表达式计算器calc的第二十三步,多行输入、进制输出、错误恢复、常量折叠、配置加载等
c语言·开发语言·atomcode
q567315237 小时前
企业级 HTTP 代理采购选型:技术评估清单 15 项
开发语言·网络·爬虫·网络协议·http·隧道ip·代理ip