SpringBoot中CommandLineRunner详解(含源码)
文章目录
- 前言
- 实例
- 导入库
- application.yaml
- Runner
- SpringBootCommandLineRunnerApplication
- 执行结果
- 先后顺序示例
- OrderRunner1
- OrderRunner2
- 执行结果
- 通常用法
- 加载初始化数据
- 示例
- 启动后打印应用信息
- 示例
- 启动异步任务
- 示例
- 接口健康检查
- 示例
- 外部服务调用
- 示例
- 参数校验
- 示例
- 动态设置配置
- 示例
- application.yaml
- MyConfig
- ConfigRunner
- 启动阻塞
- 总结
- 源码获取
- 写在最后
前言
Spring Boot的CommandLineRunner接口是一个函数式接口,用于在Spring Boot应用程序启动后执行一些初始化操作。它提供了一个run方法,该方法在应用程序启动后被调用。
使用CommandLineRunner接口,可以在应用程序启动后执行一些必要的初始化操作,例如加载配置文件、初始化数据库连接、创建默认数据等。可以通过实现CommandLineRunner接口,并重写run方法来定义自己的初始化逻辑。
实例
导入库
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.0</version>
</parent><groupId>org.example</groupId>
<artifactId>springboot-CommandLineRunner</artifactId>
<version>1.0-SNAPSHOT</version><name>Spring Boot banner</name>
<description>Spring Boot and commandLineRunner</description><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>
</dependencies>
application.yaml
server:port: 8080spring:profiles:active: dev
Runner
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;@Component
@Slf4j
public class Runner implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {log.info("The Runner start to initialize ...");}
}
SpringBootCommandLineRunnerApplication
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@Slf4j
public class SpringBootCommandLineRunnerApplication {public static void main(String[] args) {SpringApplication.run(SpringBootCommandLineRunnerApplication.class, args);log.info("The service to end");}
}
执行结果

在上面的示例中,我们创建了一个名为MyCommandLineRunner的类,并实现了CommandLineRunner接口。在run方法中,我们可以编写需要在应用程序启动后执行的初始化逻辑。
需要注意的是,实现CommandLineRunner接口的类需要被Spring容器扫描到,可以使用@Component注解或其他方式将其注册为Spring Bean。
先后顺序示例
可以通过@Order()来设置Runner的先后顺序,在上面例子的基础上增加
OrderRunner1
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;@Component
@Order(1)
@Slf4j
public class OrderRunner1 implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {log.info("The OrderRunner1 start to initialize ...");}
}
OrderRunner2
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;@Component
@Order(2)
@Slf4j
public class OrderRunner2 implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {log.info("The OrderRunner2 start to initialize ...");}
}
执行结果

通常用法

加载初始化数据
可以实现CommandLineRunner接口,在run方法中加载一些初始化数据到数据库等。适合做一些数据预加载工作。
示例
@Component
public class DataInitializer implements CommandLineRunner {@Autowiredprivate UserRepository userRepository;@Overridepublic void run(String... args) throws Exception {// 创建初始用户User admin = new User("admin", "123456");userRepository.save(admin);User normalUser = new User("user", "123456");userRepository.save(normalUser);System.out.println("数据加载完毕!");}
}
这里创建了一个 DataInitializer 类,实现 CommandLineRunner 接口。在 run() 方法中,我们注入了 UserRepository,然后创建了两个用户对象保存到数据库中。这个类会在 Spring Boot 应用启动完成后执行,从而实现了数据预加载的效果。通过 CommandLineRunner,我们可以灵活地在 Spring Boot 启动时进行一些初始化操作,如预先加载测试数据、插入管理员账户等,很好地增强了应用的功能。
假设我们有一个User模型和用户Repository,需要在Spring Boot启动时预加载几个用户数据,可以这样使用CommandLineRunner:
@Component
public class DataInitializer implements CommandLineRunner {@Autowiredprivate UserRepository userRepository;@Overridepublic void run(String... args) throws Exception {// 清除所有数据userRepository.deleteAll(); // 创建几个用户User user1 = new User("John", "john@example.com");User user2 = new User("Mary", "mary@example.com");userRepository.save(user1);userRepository.save(user2);// 打印已保存用户数System.out.println("Number of users saved: " + userRepository.count());}}
这里我们实现了CommandLineRunner接口,然后注入UserRepository bean。在run方法中,首先清空所有数据,然后创建两个用户对象并保存,最后打印已保存的用户数。这样在Spring Boot应用启动完成后,就会自动执行run方法,预加载指定的用户数据。
启动后打印应用信息
可以打印出一些应用启动信息,如启动端口、运行环境信息等,用于确认应用配置。
示例
@Component
@Slf4j
public class AppInfoPrinter implements CommandLineRunner {@Autowiredprivate Environment environment;@Overridepublic void run(String... args) throws Exception {log.info("========= 打印启动信息 =========");// 打印应用端口log.info(("端口号: " + environment.getProperty("server.port")));// 打印当前环境log.info("当前环境: " + environment.getProperty("spring.profiles.active"));// 打印JDK版本log.info("JDK 版本: " + System.getProperty("java.version"));log.info("========= 打印启动信息结束 =========");}}
执行打印结果

启动异步任务
可以使用多线程启动一些异步任务,进行后台数据处理等复杂业务逻辑。
示例
@Component
@Slf4j
public class AsyncTaskRunner implements CommandLineRunner {@Autowiredprivate AsyncTaskService asyncTaskService;@Overridepublic void run(String... args) throws Exception {log.info("========= 执行任务 =========");// 在新线程中执行任务new Thread(() -> {asyncTaskService.doTaskOne();asyncTaskService.doTaskTwo();asyncTaskService.doTaskThree();}).start();}}@Service
@Slf4j
class AsyncTaskService {public void doTaskOne() {log.info("执行任务1");}public void doTaskTwo() {log.info("执行任务2");}public void doTaskThree() {log.info("执行任务3");}
}
执行结果
[ main] org.example.runner.AsyncTaskRunner : ========= 执行任务 =========
[ Thread-1] org.example.runner.AsyncTaskService : 执行任务1
[ Thread-1] org.example.runner.AsyncTaskService : 执行任务2
[ Thread-1] org.example.runner.AsyncTaskService : 执行任务3
接口健康检查
可以调用并验证依赖服务的健康状态,如果不正常可以终止Spring Boot启动。
示例
@Component
@Slf4j
public class HealthCheckRunner implements CommandLineRunner {@Autowiredprivate DatabaseService databaseService;@Autowiredprivate MessageQueueService messageQueueService;@Overridepublic void run(String... args) throws Exception {if(!databaseService.isConnected()) {log.error("数据库服务不可用,退出应用!");System.exit(1);}if(!messageQueueService.isConnected()) {log.error("消息队列服务不可用,退出应用!");System.exit(1);}log.info("所有服务正常,应用启动。");}
}
这里我们注入两个依赖服务 DatabaseService 和 MessageQueueService。在run方法中,调用它们的健康检查方法,如果任何一个服务不可用,则直接调用System.exit(1)退出Spring Boot应用启动。
外部服务调用
可以在启动时调用外部服务,进行验证、数据同步等操作。
示例
@Component
public class OtherServiceCheckRunner implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {// 健康检查的URLString healthCheckUrl = "http://localhost:8080/actuator/health";RestTemplate restTemplate = new RestTemplate();// 发送GET请求进行健康检查String response = restTemplate.getForObject(healthCheckUrl, String.class);// 根据响应判断健康状态if (response.contains("\"status\":\"UP\"")) {System.out.println("Application is healthy");} else {System.out.println("Application is not healthy");}}
}
参数校验
可以对输入的运行参数做校验,如果不满足条件可以终止Spring Boot启动。
示例
@Component
@Slf4j
public class ParameterValidator implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {// 校验参数1if(args.length < 2) {log.error("参数不正确,请传入至少2个参数!");System.exit(1);}// 校验参数2是否为数字if(!args[1].matches("\\d+")) {log.error("第二个参数必须是数字!");System.exit(1);}// 校验通过,应用继续启动log.info("参数校验通过,应用启动中...");}
}
在run方法中,我们可以对main方法输入的参数args进行自定义校验:
- 检查参数数量
- 校验参数类型
如果参数不满足需求,可以直接调用System.exit(1)来终止Spring Boot的启动。这样就可以在应用启动前验证参数的正确性,避免应用启动后发生未知错误。
动态设置配置
可以根据运行参数等条件动态设置Spring Boot的配置,实现不同环境的适配。
示例
application.yaml
myconfig:foo: 十五bar: 1
MyConfig
@Component
@Data
@ConfigurationProperties(prefix = "myconfig")
public class MyConfig {private String foo;private int bar;// getter和setter方法省略@Overridepublic String toString() {return "MyConfig{" +"foo='" + foo + '\'' +", bar=" + bar +'}';}
}
ConfigRunner
@Component
@EnableConfigurationProperties(MyConfig.class)
public class ConfigRunner implements CommandLineRunner {@Autowiredprivate MyConfig myConfig;@Overridepublic void run(String... args) throws Exception {
// 打印当前配置System.out.println("Current config: " + myConfig);// 动态设置配置myConfig.setFoo("new value");myConfig.setBar(100);// 打印更新后的配置System.out.println("Updated config: " + myConfig);}
}
启动阻塞
可以使应用启动后阻塞住主线程,防止main方法直接退出,从而保持Spring Boot应用运行。
示例
@Component
@Slf4j
public class StartBlocker implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {// 加载提示信息log.info("正在等待管理员授权...");// 等待授权,阻塞启动流程waitAuth();// 授权完成后继续启动log.info("管理员已授权,应用启动中...");}private void waitAuth() {// 死循环模拟等待管理员操作授权while(true) {try {Thread.sleep(1000);} catch (InterruptedException e) {break;}}}}
总结
通过 CommandLineRunner,我们可以深度控制 Spring Boot 应用的启动流程,在应用启动阶段增强各种自定义逻辑。是 Spring Boot 提供的一个很实用的扩展点。
源码获取
如果需要完整源码请关注公众号"架构殿堂" ,回复 "SpringBoot+CommandLineRunner"即可获得
写在最后
感谢您的支持和鼓励! 😊🙏
如果大家对相关文章感兴趣,可以关注公众号"架构殿堂",会持续更新AIGC,java基础面试题, netty, spring boot, spring cloud等系列文章,一系列干货随时送达!

相关文章:
SpringBoot中CommandLineRunner详解(含源码)
文章目录 前言实例导入库application.yamlRunnerSpringBootCommandLineRunnerApplication执行结果 先后顺序示例OrderRunner1OrderRunner2执行结果 通常用法加载初始化数据示例 启动后打印应用信息示例 启动异步任务示例 接口健康检查示例 外部服务调用示例 参数校验示例 动态设…...
通信基础(一):数据传输基础
一、波特率与比特率关系 比特率(信息传输速率、信息速率):指单位时间内在信道上传 送的数据量(即比特数),单位为比特每秒 (bit/s), 简记为b/s或bps。 波特率与比特率有如下换算关系: bitbaud *log 2(N) 其中, N是码元总类数。 特别注意ÿ…...
故障诊断模型 | Maltab实现BiLSTM双向长短期记忆神经网络故障诊断
文章目录 效果一览文章概述模型描述源码设计参考资料效果一览 文章概述 故障诊断模型 | Maltab实现BiLSTM双向长短期记忆神经网络故障诊断 模型描述 利用各种检查和测试方法,发现系统和设备是否存在故障的过程是故障检测;而进一步确定故障所在大致部位的过程是故障定位。故障…...
物联网和互联网医院小程序:如何实现医疗设备的远程监测和管理?
物联网(IoT)技术的发展为医疗设备的远程监测和管理提供了巨大的机会。结合互联网医院小程序,我们可以实现对医疗设备的远程访问、监控和管理,从而提高医疗服务的质量和效率。本文将介绍如何实现医疗设备的远程监测和管理ÿ…...
sharepoint2016-2019升级到sharepoint订阅版
一、升级前准备: 要建立新的sharepoint订阅版环境,需求如下: 1.单服务器硬件需求CPU 4核,内存24G以上,硬盘300G(根据要迁移的数量来扩容大小等); 2.操作系统需要windows server 20…...
CTFHub | MySQL流量、Redis流量、MongoDB流量的WriteUp
文章目录 MySQL流量题目题解 Redis流量题目题解 MongoDB流量题目题解 数据库类流量题需要用到Wireshark截取数据包,然后进行分析。 WireShark是非常流行的网络封包分析工具,可以截取各种网络数据包,并显示数据包详细信息。常用于开发测试过程…...
NSS刷题 js前端修改 os.path.join漏洞
打算刷一遍nssweb题(任重道远) 前面很简单 都是签到题 这里主要记录一下没想到的题目 [GDOUCTF 2023]hate eat snake js前端修改 这里 是对js的处理 有弹窗 说明可能存在 alert 我们去看看js 这里进行了判断 如果 getScore>-0x1e9* 我们结合上面…...
ArcGIS Maps SDK for JS:隐藏地图边框
文章目录 1 问题描述2 解决方案 1 问题描述 近期,将ArcGIS Api for JS v4.16更新到了ArcGIS Maps SDK for JS v4.27,原本去除地图的css代码失效了。 v4.26及以前版本 ,需要用.esri-view-surface--inset-outline:focus::after 控制边框属性。…...
带你秒懂MySQL!! 一万字详细知识点和基础操作 欢迎评论区怼我 (三)
表操作 创建 # 创建表结构 create table user(id int comment ID,唯一标志,username varchar(20) comment 用户名,name varchar(10) comment 姓名,age int comment 年龄,gender char(1) comment 性别 ) comment 用户表; 约束 非空约束限制该字段值不为nullnot null唯一约束保证…...
kubeadmin部署k8s1.27.4
kubeadmin部署k8s1.27.4 环境介绍 IP主机名资源配置系统版本192.168.117.170k8s-master2c2g200gCentos7.9192.168.117.171k8s-node12c2g200gCentos7.9192.168.117.172k8s-node22c2g200gCentos7.9 编辑本地解析且修改主机名 三台主机都要做 vim /etc/hosts配置主机名 mast…...
【Aurix Tricore】HighTec启动代码crt0-tc37x.c分析笔记
1. 前言 crt0是hightec 在其toolchain的gcc库中实现启动startup功能的核心代码。 HighTec已为tc3xx设置了一些默认的启动行为。在此启动过程中,目标被初始化并设置为其默认值。启动文件的代码在进入main()函数之前执行。之后,执行main()函数的构造函数。 编译器附带的启动…...
Linux高级命令(扩展)
一、find命令 1、find命令作用 在Linux操作系统中,find命令主要用于进行文件的搜索。 2、基本语法 # find 搜索路径 [选项 选项的值] ... 选项说明: -name :根据文件的名称搜索文件,支持*通配符 -type :f代表普通文…...
LLM在text2sql上的应用 | 京东云技术团队
一、前言: 目前,大模型的一个热门应用方向text2sql它可以帮助用户快速生成想要查询的SQL语句。那对于用户来说,大部分简单的sql都是正确的,但对于一些复杂逻辑来说,需要用户在产出SQL的基础上进行简单修改,…...
【MySQL】 复合查询 | 内外连接
文章目录 1. 复合查询多表笛卡尔积自连接在where子句使用子查询单行子查询多行子查询in关键字all关键字any关键字 多列子查询 在from子句中使用子查询合并查询unionunion all 2. 内连接3. 外连接左外连接右外连接 1. 复合查询 多表笛卡尔积 显示雇员名、雇员工资以及所在部门…...
【linux】麒麟v10安装openjdk8
openjdk的官网 点我就到官网 jdk8的网址 安装 yum install -y java-1.8.0-openjdk-devel 出现Complete! 就是安装完成。 验证 java -version配置环境变量 查找安装路径 find / -name java 修改配置文件 vim /etc/profile 增加内容 export JAVA_HOME/usr/lib/jvm/j…...
项目部署与上线
文章目录 多环境前端后端 原始部署安装nginx部署前端部署后端 宝塔Linux部署前端部署后端部署 Docker部署Docker平台部署(√)绑定域名跨域问题解决 多环境 项目部署上线 原始前端/后端宝塔Linux容器容器平台 多环境 同一套项目代码,在不…...
系统架构主题之八:非功能性需求对系统架构及设计的影响
从大的方面来讲,软件系统的需求分为功能性需求和非功能性需求。功能性需求一般由业务分解而来,是直接面向用户的需求,也是直接体现用户价值的需求。非功能性需求一般多是由功能性需求的内在要求衍生而来,其价值更多的体现在对功能…...
盛元广通化工实验室管理系统
随着时代的进步和网络技术的普及应用,管理化工实验室的日常工作和实验过程,企业科研单位对信息化、智能化和安全性日趋要求严格,根据化工实验室的实际需求出发,从完整的开发框架、调度引擎和丰富的组件、页面样例等快速响应应用需…...
代码没注释?一个方法几百行?
干程序员的都有接收别人的代码的经历,大部分时候,我们都会偷偷骂一句“这人是傻逼吧,这代码写的这么烂!” “一个方法写几百行,还没有注释,鬼知道写的什么东西!” 现在,你不需要为…...
Angular-04:指令
① 内置指令1.1 *ngIf 结构指令1.2 [hidden] 属性指令1.3. *ngFor 结构指令1.4 *ngSwitch 结构指令 ② 自定义指令用法 指令是angular操作dom的途径,分为属性指令和结构指令。属性指令:修改元素的外观或行为。使用 [ ] 包裹。结构指令:增加、…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
