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 *&----------------------------------------------------------…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...