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 提供的启动完成回调接口,用于在容器完全初始化后执行系统级初始化逻辑,常用于缓存预热、配置校验、任务启动等场景。

相关推荐
石工记2 小时前
windows 10直接安装多个JDK
java·开发语言
菜鸟233号2 小时前
力扣669 修剪二叉搜索树 java实现
java·数据结构·算法·leetcode
健康平安的活着2 小时前
springboot+sse的实现案例
java·spring boot·后端
05大叔2 小时前
多线程的学习
java·开发语言·学习
小萌新上大分3 小时前
synchronized的8锁问题(区分默认用的是那把锁) 笔记云备份
java·java多线程·synchronized·synchronized关键字·synchronized用法·多线程买票问题·java锁机制
sino爱学习3 小时前
别再踩 Stream 的坑了!Java 函数式编程安全指南
java·后端
Sunsets_Red3 小时前
2025 FZYZ夏令营游记
java·c语言·c++·python·算法·c#
自由生长20243 小时前
从流式系统中思考-C++生态和Java生态的区别
java·c++
培培说证4 小时前
2026大专Java开发工程师,考什么证加分?
java·开发语言·python