CommandLineRunner 是什么?

Spring Boot 里,CommandLineRunner 是一个非常常用、但又容易被低估的启动钩子接口


一、CommandLineRunner 是什么?

CommandLineRunnerSpring Boot 提供的一个接口

java 复制代码
public interface CommandLineRunner {
    void run(String... args) throws Exception;
}

👉 只做一件事:

在 Spring Boot 应用启动完成后,执行一段代码


二、什么时候执行?(生命周期位置)

Spring Boot 启动顺序(简化版):

复制代码
1. SpringApplication.run()
2. 创建 ApplicationContext
3. 扫描 Bean / 注入依赖
4. 执行 @PostConstruct
5. 执行 CommandLineRunner / ApplicationRunner
6. 启动完成(应用对外可用)

📌 关键点:

  • 所有 Bean 已经初始化完成
  • @Autowired 可以正常用
  • 适合做 启动后初始化逻辑

三、最基本用法

方式一:实现接口(最常见)

java 复制代码
@Component
public class InitRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("Spring Boot 启动完成");
    }
}

启动后控制台输出:

复制代码
Spring Boot 启动完成

方式二:@Bean 方式(更灵活)

java 复制代码
@Bean
public CommandLineRunner init() {
    return args -> {
        System.out.println("执行初始化逻辑");
    };
}

适合 配置类中集中管理启动逻辑


四、args 是什么?

args 就是 启动 JVM 时的命令行参数

bash 复制代码
java -jar app.jar --env=prod --debug=true

run 里:

java 复制代码
@Override
public void run(String... args) {
    for (String arg : args) {
        System.out.println(arg);
    }
}

输出:

复制代码
--env=prod
--debug=true

📌 注意:

  • Spring 的 application.properties 参数也会被解析,但这里拿到的是原始命令行

五、多个 CommandLineRunner 的执行顺序

如果你有多个 Runner:

java 复制代码
@Component
@Order(1)
public class FirstRunner implements CommandLineRunner {
    public void run(String... args) {
        System.out.println("First");
    }
}
java 复制代码
@Component
@Order(2)
public class SecondRunner implements CommandLineRunner {
    public void run(String... args) {
        System.out.println("Second");
    }
}

执行顺序:

复制代码
First
Second

📌 规则:

  • 数字 越小越先执行
  • 也可以实现 Ordered 接口

六、和 ApplicationRunner 的区别(面试常问)

对比项 CommandLineRunner ApplicationRunner
参数 String... args ApplicationArguments
参数解析 需要自己拆 已解析(key-value)
易用性 简单 更强
使用频率 ⭐⭐⭐⭐⭐ ⭐⭐⭐

ApplicationRunner 示例:

java 复制代码
@Component
public class AppRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) {
        args.getOptionNames().forEach(System.out::println);
    }
}

七、常见使用场景(非常重要)

1️⃣ 初始化缓存(Redis / 本地缓存)

java 复制代码
@Component
public class CacheInitRunner implements CommandLineRunner {

    @Autowired
    private UserService userService;

    @Override
    public void run(String... args) {
        userService.loadAllUsersToCache();
    }
}

✔ 广告 / 游戏后台非常常见

✔ 你之前提到 Redis、广告初始化,这个用法很典型


2️⃣ 启动时校验配置

java 复制代码
@Override
public void run(String... args) {
    if (StringUtils.isEmpty(apiKey)) {
        throw new RuntimeException("API_KEY 未配置");
    }
}

📌 失败就让服务启动失败


3️⃣ 初始化定时任务 / 监听器

java 复制代码
@Override
public void run(String... args) {
    taskManager.start();
}

4️⃣ 数据迁移 / 表结构检查(轻量级)

java 复制代码
@Override
public void run(String... args) {
    migrateService.checkAndFix();
}

5️⃣ 游戏 / 广告 SDK 初始化

你做广告变现,这种非常常见:

java 复制代码
@Override
public void run(String... args) {
    AdConfig.init();
    SdkManager.load();
}

八、和 @PostConstruct 的区别(重点)

对比 @PostConstruct CommandLineRunner
执行时机 单个 Bean 初始化后 全部 Bean 初始化完成
是否能注入其他 Bean 有风险 安全
执行次数 每个 Bean 一次 全局一次
适合做 Bean 内部初始化 系统级初始化

📌 经验法则:

  • Bean 自己的事 → @PostConstruct
  • 系统启动的事 → CommandLineRunner

九、注意事项(踩坑点)

❌ 1. 不要写阻塞死循环

java 复制代码
@Override
public void run(String... args) {
    while (true) {} // ❌ 服务卡死
}

✔ 如果要长任务,新开线程


❌ 2. 不要写超慢逻辑

  • 拖慢服务启动
  • Kubernetes / 云环境容易被判定启动失败

✔ 推荐做法

java 复制代码
@Override
public void run(String... args) {
    CompletableFuture.runAsync(() -> initHeavyTask());
}

十、一句话总结

CommandLineRunner 是 Spring Boot 提供的启动完成回调接口,用于在容器完全初始化后执行系统级初始化逻辑,常用于缓存预热、配置校验、任务启动等场景。

相关推荐
寻星探路7 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
曹牧9 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
爬山算法10 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
kfyty72510 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
猫头虎10 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
李少兄10 小时前
在 IntelliJ IDEA 中修改 Git 远程仓库地址
java·git·intellij-idea
忆~遂愿10 小时前
ops-cv 算子库深度解析:面向视觉任务的硬件优化与数据布局(NCHW/NHWC)策略
java·大数据·linux·人工智能
小韩学长yyds10 小时前
Java序列化避坑指南:明确这4种场景,再也不盲目实现Serializable
java·序列化
仟濹10 小时前
【Java基础】多态 | 打卡day2
java·开发语言
Re.不晚10 小时前
JAVA进阶之路——无奖问答挑战2
java·开发语言