CommandLineRunner 是什么?

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


一、CommandLineRunner 是什么?

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

相关推荐
小羊没烦恼!3 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里3 天前
java中的继承和多态的区别
java
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕3 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码3 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖3 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时3 天前
01-06-A-JVM排查实战详解
java·jvm
vipxieliang3 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
ba_pi3 天前
mysql 查询所有表名并授权
java
ProcessOn官方账号3 天前
java函数式编程--入门基础
java·编程·函数式编程