Spring Boot 应用程序生命周期扩展点妙用
文章目录
- 前言
- 1. 应用程序生命周期扩展点
- 2. 使用场景示例
- 2.1 SpringApplicationRunListener
- 2.2 ApplicationEnvironmentPreparedEvent
- 2.3 ApplicationPreparedEvent
- 2.4 ApplicationStartedEvent
- 2.5 ApplicationReadyEvent
- 2.6 ApplicationFailedEvent
- 2.7 ApplicationRunner
- 3. 参考文档
前言
上一篇我们着重按照分类讲解了一下Spring Boot的常见扩展点,接下来我们讲解一下Spring Boot 的应用程序生命周期扩展点的一些妙用。
Spring Boot的应用程序生命周期扩展点是一些接口,可以让开发者在应用程序的不同生命周期阶段插入自己的逻辑。这些扩展点可以帮助开发者在应用程序启动、关闭、重启等阶段执行一些额外的操作。
下面介绍几个常用的应用程序生命周期扩展点:
-
ApplicationRunner和CommandLineRunner:这两个接口可以在应用程序启动完成后执行一些初始化的操作。例如,你可以实现一个ApplicationRunner来初始化数据库连接池,或者实现一个CommandLineRunner来加载一些初始化数据。
-
ApplicationPreparedEvent:这个事件在应用程序准备启动时触发,可以在其中执行一些准备工作。例如,你可以监听这个事件,然后在应用程序启动之前执行一些配置文件的加载操作。
-
ApplicationStartedEvent:这个事件在应用程序开始启动时触发,可以在其中执行一些初始化的操作。例如,你可以监听这个事件,然后在应用程序启动之前执行一些初始化的逻辑。
-
ApplicationReadyEvent:这个事件在应用程序完全启动后触发,可以在其中执行一些额外的初始化操作。例如,你可以监听这个事件,然后在应用程序启动之后执行一些数据缓存的加载操作。
-
ApplicationFailedEvent:这个事件在应用程序启动失败时触发,可以在其中执行一些错误处理的逻辑。例如,你可以监听这个事件,然后在应用程序启动失败时发送一封错误报告邮件。
通过实现这些扩展点,你可以在应用程序的不同生命周期阶段插入自己的逻辑,并且可以方便地扩展和定制应用程序的行为。这些扩展点的使用可以帮助你更好地管理和控制应用程序的生命周期,提高应用程序的可靠性和可维护性。
还是那句老话,这个不是八股文,只有知道才遇到相似场景的才能知道怎么用。学以致用,是我们分享内容的不变的宗旨。

冰点出品,必属精品
1. 应用程序生命周期扩展点
应用程序生命周期扩展点是指在Spring Boot应用程序的生命周期中,提供了一系列的扩展点,开发人员可以通过实现这些扩展点来对应用程序的生命周期进行控制和定制。这些扩展点主要包括以下几个:

此图来自网络
2. 使用场景示例
2.1 SpringApplicationRunListener
它是一个监听器接口,用于在Spring应用程序的运行生命周期中监听和响应相关事件。可以通过实现该接口来自定义应用程序的启动和关闭行为。
好的,让我们来看一个使用SpringApplicationRunListener的例子。
假设你正在开发一个在线学习平台的后端系统。在应用程序启动时,你想要执行一些特定的操作,例如加载配置文件、初始化数据库连接等。这时候,你可以使用SpringApplicationRunListener来监听应用程序的启动事件,并在事件触发时执行这些操作。
首先,需要创建一个名为CustomSpringApplicationRunListener的类,实现SpringApplicationRunListener接口,并重写相应的方法。CustomSpringApplicationRunListener类实现了SpringApplicationRunListener接口的各个方法。你可以根据需要在这些方法中执行特定的操作。例如,在starting方法中,你可以执行启动前的操作,如加载配置文件;在started方法中,你可以执行应用程序已启动的操作,如启动后台任务等。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;public class CustomSpringApplicationRunListener implements SpringApplicationRunListener {public CustomSpringApplicationRunListener(SpringApplication application, String[] args) {}@Overridepublic void starting() {System.out.println("Application starting...");// 执行启动前的操作,如加载配置文件等}@Overridepublic void environmentPrepared(ConfigurableEnvironment environment) {System.out.println("Environment prepared...");// 执行环境准备的操作,如设置环境变量等}@Overridepublic void contextPrepared(ConfigurableApplicationContext context) {System.out.println("Context prepared...");// 执行上下文准备的操作,如初始化数据库连接等}@Overridepublic void contextLoaded(ConfigurableApplicationContext context) {System.out.println("Context loaded...");// 执行上下文加载的操作,如配置Bean等}@Overridepublic void started(ConfigurableApplicationContext context) {System.out.println("Application started...");// 执行应用程序已启动的操作,如启动后台任务等}@Overridepublic void running(ConfigurableApplicationContext context) {System.out.println("Application running...");// 执行应用程序运行的操作,如执行定时任务等}@Overridepublic void failed(ConfigurableApplicationContext context, Throwable exception) {System.out.println("Application failed to start...");// 执行应用程序启动失败的操作,如记录错误日志等}
}
接下来,需要在应用程序的META-INF目录下创建一个名为spring.factories的文件,并在其中配置CustomSpringApplicationRunListener类。
org.springframework.boot.SpringApplicationRunListener=com.example.CustomSpringApplicationRunListener
这样,当你的应用程序启动时,Spring Boot将会自动创建CustomSpringApplicationRunListener实例,并在适当的时机调用对应的方法。
这只是一个简单的例子,展示了如何使用SpringApplicationRunListener接口来监听应用程序的启动事件,并在事件触发时执行特定的操作 。实际项目可能需要考虑的问题更多,比如加载顺序,依赖关系等等。
2.2 ApplicationEnvironmentPreparedEvent
该事件在应用程序启动前触发,用于在环境准备阶段执行一些操作,例如:加载配置文件、设置系统属性等。
当应用程序的环境准备就绪时,可以使用ApplicationEnvironmentPreparedEvent来执行某些操作。例如,假设你正在开发一个基于Spring Boot的社交媒体应用程序,你可以使用这个事件来加载特定环境的配置文件,以便根据不同的环境配置进行不同的操作。
在这个例子中,我们可以通过创建一个实现了ApplicationListener接口的类来监听ApplicationEnvironmentPreparedEvent事件。然后在onApplicationEvent方法中,我们可以根据当前的环境配置加载不同的配置文件。可能举的事例不是很合理,大家能够理解就OK。
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;public class EnvironmentPreparedListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {@Overridepublic void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {String environment = event.getEnvironment().getActiveProfiles()[0];// 根据环境配置加载不同的配置文件if (environment.equals("dev")) {// 加载dev环境的配置文件} else if (environment.equals("prod")) {// 加载prod环境的配置文件} else if (environment.equals("windows")) {// 加载prod环境的配置文件} else if (environment.equals("linux")) {// 加载prod环境的配置文件}// 执行其他操作}
}
在Spring Boot应用程序的入口类中,我们可以将这个监听器注册到Spring容器中:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SocialMediaApplication {public static void main(String[] args) {SpringApplication application = new SpringApplication(SocialMediaApplication.class);application.addListeners(new EnvironmentPreparedListener());application.run(args);}
}
这样,当应用程序的环境准备就绪时,EnvironmentPreparedListener中的onApplicationEvent方法将会被触发,你可以在该方法中执行一些特定于环境配置的操作,例如加载特定的配置文件。这在开发和部署应用程序时非常有用,可以根据不同的环境配置进行不同的初始化操作。
2.3 ApplicationPreparedEvent
该事件在应用程序上下文创建完成后触发,用于在应用程序准备阶段执行一些操作,例如:创建和初始化Bean等。
好的,我可以举一个使用ApplicationPreparedEvent的例子。
假设你正在开发一个电子商务网站的后端系统,当应用程序启动时,你希望自动初始化一些商户数据到缓存中。
首先,你需要创建一个实现ApplicationListener接口的类,用于监听ApplicationPreparedEvent事件。例如,你可以创建一个名为DataInitializationListener的类:
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.context.ApplicationListener;public class DataInitializationListener implements ApplicationListener<ApplicationPreparedEvent> {@Overridepublic void onApplicationEvent(ApplicationPreparedEvent event) {// 在应用程序准备阶段执行初始化数据的操作initializeData();}private void initializeData() {// 在这里执行初始化数据的逻辑,例如将商户数据加载到缓存中去// ...}
}
然后,在你的Spring Boot应用程序的主类中,将DataInitializationListener注册为一个bean,以便在应用程序启动时被自动调用:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;@SpringBootApplication
public class YourApplication {public static void main(String[] args) {SpringApplication.run(YourApplication.class, args);}@Beanpublic DataInitializationListener dataInitializationListener() {return new DataInitializationListener();}
}
现在, 运行应用程序时,DataInitializationListener将会监听ApplicationPreparedEvent事件,并在应用程序准备阶段执行initializeData方法,从而实现自动初始化商户数据的功能。
ApplicationPreparedEvent事件是在应用程序准备阶段触发的,该阶段是在ApplicationContext创建之前,但已经加载了bean定义。因此,你可以在该事件中执行与应用程序初始化相关的操作。
2.4 ApplicationStartedEvent
该事件在应用程序启动完成后触发,用于在应用程序启动后执行一些操作,例如:向日志中输出启动信息等。
2.5 ApplicationReadyEvent
该事件在应用程序准备就绪后触发,用于在应用程序运行期间执行一些操作,例如:启动定时任务、初始化缓存等。
2.6 ApplicationFailedEvent
该事件在应用程序启动失败后触发,用于在应用程序启动失败时执行一些操作,例如:记录日志、发送告警等。
当应用程序启动失败时,可以使用ApplicationFailedEvent事件来发送通知或记录日志,以便进行故障排查和问题解决。例如,假设我们的应用程序依赖于数据库连接,如果数据库连接失败导致应用程序无法启动,我们可以创建一个监听器类来处理这种情况。下面是一个简单的例子:
创建一个实现ApplicationListener接口的监听器类,例如ApplicationFailedListener:
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.context.ApplicationListener;public class ApplicationFailedListener implements ApplicationListener<ApplicationFailedEvent> {@Overridepublic void onApplicationEvent(ApplicationFailedEvent event) {// 获取失败的异常信息Throwable throwable = event.getException();// 发送通知或记录日志,进行故障排查和问题解决System.out.println("应用程序启动失败:" + throwable.getMessage());}
}
然后,在Spring Boot应用程序的入口类中,将该监听器类注册为一个Bean:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;@SpringBootApplication
public class Application {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);// 其他应用程序逻辑}@Beanpublic ApplicationFailedListener applicationFailedListener() {return new ApplicationFailedListener();}
}
现在,当应用程序启动失败时,ApplicationFailedListener监听器中的onApplicationEvent方法将被调用,并打印出失败的异常信息。
这个例子只是一个简单的示例,你可以根据实际需求进行扩展和定制化。你可以根据具体的业务场景,使用该事件来发送邮件、短信通知、记录日志或进行其他故障处理操作。
2.7 ApplicationRunner
可以利用ApplicationRunner接口来执行一些应用程序启动后的初始化任务。
@Component
public class MyApplicationRunner implements ApplicationRunner {@Overridepublic void run(ApplicationArguments args) throws Exception {// 在应用程序启动后执行的任务System.out.println("应用程序启动后执行的任务");// 可以在这里执行一些初始化操作,如加载配置文件、初始化数据库连接等}
}
我们创建了一个名为MyApplicationRunner的类,并实现了ApplicationRunner接口。在类中,我们重写了run方法,该方法会在应用程序启动后被自动调用。在run方法中,可以编写需要在应用程序启动后执行的任务。例如,可以在这里加载配置文件、初始化数据库连接、创建一些初始数据等。
要让Spring Boot应用程序自动执行该任务,需要将MyApplicationRunner类注解为一个@Component或者@Service等Spring Bean,并将其注册到Spring容器中。这样,当应用程序启动时,Spring Boot会自动调用MyApplicationRunner的run方法。
这样 也就可以利用ApplicationRunner接口来执行一些应用程序启动后的初始化任务。
3. 参考文档
- Spring Boot官方文档:https://spring.io/projects/spring-boot
- Spring Boot Reference Guide:https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/
- Spring Boot官方文档相关 https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-customizing-bean-definitions
- Spring Boot 自动配置 https://docs.spring.io/spring-boot/docs/3.1.2/reference/html/auto-configuration-classes.html#appendix.auto-configuration-classes

👏好了,本次的Spring Boot 的扩展点分享就到这儿,我是冰点,下次见。如果我的文章对你有所收获,可以给个赞。如果有疑问可以在评论区留言。
相关文章:
Spring Boot 应用程序生命周期扩展点妙用
文章目录 前言1. 应用程序生命周期扩展点2. 使用场景示例2.1 SpringApplicationRunListener2.2 ApplicationEnvironmentPreparedEvent2.3 ApplicationPreparedEvent2.4 ApplicationStartedEvent2.5 ApplicationReadyEvent2.6 ApplicationFailedEvent2.7 ApplicationRunner 3. 参…...
【Nodejs】操作mongodb数据库
1.简介 Mongoose是一个让我们可以通过Node来操作MongoDB的模块。Mongoose是一个对象文档模型(ODM)库,它对Node原生的MongoDB模块进行了进一步的优化封装,并提供了更多的功能。在大多数情况下,它被用来把结构化的模式应用到一个MongoDB集合,并…...
SQL-每日一题【619.只出现一次的最大数字】
题目 MyNumbers 表: 单一数字 是在 MyNumbers 表中只出现一次的数字。 请你编写一个 SQL 查询来报告最大的 单一数字 。如果不存在 单一数字 ,查询需报告 null 。 查询结果如下例所示。 示例 1: 示例 2: 解题思路 1.题目要求我…...
紫光FPGA试用--软件篇
目录 一 软件安装启动 二 如何打开IP核?查看/修改现有IP核参数? 三 如何定义引脚? 四 如何下载code进入FPGA? 1. 下载到FPGA芯片内: 2.下载到外部FLASH中 五 如何进入在线调试模式,调试步骤 操作步骤ÿ…...
PDF添加水印以及防止被删除、防止编辑与打印
方法记录如下: 1、添加水印; 2、打印输出成一个新的pdf; 3、将pdf页面输出成一张张的图片:(福昕pdf操作步骤如下) 4、将图片组装成一个新的pdf:(福昕pdf操作步骤如下)…...
el-tree转换为表格样式的记录2
上一篇文章记录的是自己将树状数据转换为表格形式。但是出现了一个小bug,点击子节点时候会选中父节点,这个是正常需求没问题。但是我点击父节点时候取消所有子节点,父节点 选择也会失去,这是我不想要执行的。例如一个页面里面有主…...
MS1826B HDMI 1进4出 视频拼接芯片
MS1826B 是一款多功能视频处理器,包含 4 路独立 HDMI 音视频输出通道、1 路 HDMI 音视 频输入通道以及 1 路独立可配置为输入或者输出的 SPDIF、I2S 音频信号。支持 4 个独立的字库定 制型 OSD;可处理隔行和逐行视频或者图形输入信号;有四路独…...
Spring之注解
SpringIOC注解 组件添加标记注解: Component:该注解标记类表示该类为一个普通类,表示为IOC中的一个组件bean Repository:该注解用于将数据访问层(Dao层)的类标识为Spring中的Bean Service&…...
【UniApp开发小程序】悬浮按钮+出售闲置商品+商品分类选择【基于若依管理系统开发】
文章目录 界面效果界面实现悬浮按钮实现商品分类选择界面使元素均匀分布 闲置商品描述信息填写界面价格校验 界面效果 【悬浮按钮】 【闲置商品描述信息填写界面】 【商品分类选择界面】 【分类选择完成】 界面实现 悬浮按钮实现 悬浮按钮漂浮于页面之上,等页面…...
一百三十三、Hive——Hive外部表加载含有JSON格式字段的CSV文件数据
一、目标 在Hive的ODS层建外部表,然后加载HDFS中的CSV文件数据 注意:CSV文件中含有未解析的JSON格式的字段数据,并且JSON字段中还有逗号 二、第一次建外部表,直接以,分隔行字段,结果JSON数据只显示一部分…...
rust gtk 桌面应用 demo
《精通Rust》里介绍了 GTK框架的开发,这篇博客记录并扩展一下。rust 可以用于桌面应用开发,我还挺惊讶的,大学的时候也有学习过 VC,对桌面编程一直都很感兴趣,而且一直有一种妄念,总觉得自己能开发一款很好…...
《嵌入式 - 工具》J-link读写MCU内部Flash
1 J-Link简介 J-Link是SEGGER公司为支持仿真ARM内核芯片推出的JTAG仿真器。配合IAR EWAR,ADS,KEIL,WINARM,RealView等集成开发环境支持所有ARM7/ARM9/ARM11,Cortex M0/M1/M3/M4, Cortex A5/A8/A9等内核芯片的仿真,是学…...
算法练习-LeetCode1071. Greatest Common Divisor of Strings
题目地址:LeetCode - The Worlds Leading Online Programming Learning Platform Description: For two strings s and t, we say "t divides s" if and only if s t ... t (i.e., t is concatenated with itself one or more times). Given two strin…...
Nuget不小心用sudo下载后怎么在user里使用
问题发生 协同开发的过程中,同时在dotnet里面添加了nuget的grpc包,在不清楚的情况下执行自动生成脚本,下载nuget包失败,说是权限不足,于是就使用了sudo进行自动生成,结果在下一次重新打包的过程中ÿ…...
软件测试技能大赛环境搭建及系统部署报告
环境搭建及系统部署报告 环境搭建与配置过程(附图) JDK环境变量配置截图 【截取JDK环境变量配置截图】 查看JDK版本信息截图 【截取使用命令查看JDK版本信息截图,必须截取查看信息成功截图】 root账号成功登录MySQL截图 【截取使用root账…...
浅谈现代通信技术
目录 1.传统通信方法 2.传统通信方式的缺点 3.现代通信技术 4.现代通信技术给人类带来的福利 1.传统通信方法 传统通信方法指的是在数字化通信之前使用的传统的通信方式。以下是一些常见的传统通信方法: 1. 书信:通过邮件或快递等方式发送纸质信件。这…...
windows环境下adb 下载和配置,连接手机。
ADB下载地址: https://adbdownload.com/ 选择下载windows系统的。 下载后解压,查看adb.exe所在的目录,如下 这里将路径复制下来:D:\ADB 配置到系统环境变量中。 然后再打开cmd,输入adb version查看版本。 出现…...
[STL]list使用介绍
[STL]list使用 注:本文测试环境是visual studio2019。 文章目录 [STL]list使用1. list介绍2. 构造函数3. 迭代器相关函数begin函数和end函数rbegin函数和rend函数 4. 容量相关函数empty函数size函数 5. 数据修改函数push_back函数和pop_back函数push_front函数和pop…...
k8s服务发现之第五弹--使用 Service 连接到应用
Kubernetes 的网络模型 通过前面教程的学习,我们已经可以将容器化的应用程序在 Kubernetes 中运行起来,并且发布到 Kubernetes 内/外的网络上。 通常,Docker 使用一种 host-private 的联网方式,在此情况下,只有两个容…...
SAP ABAP 自定义表数据导入
一:效果展示: 读取 Excel 数据到 SAP 数据库表。 二:源码: *&---------------------------------------------------------------------* *& Report ZTEST_DRW02 *&----------------------------------------------------------…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
Unity UGUI Button事件流程
场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...
Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
