最稳妥方式是使用CommandLineRunner或ApplicationRunner接口,二者均在Spring容器完全启动、所有Bean就绪后执行,支持@Order控制顺序;@PostConstruct和静态块等时机过早,不适合依赖外部资源的初始化。

Spring Boot 启动时执行特定初始化脚本,核心在于选对**执行时机**和**依赖可用性**。不能写在 main 方法里(容器未就绪),也不能盲目用 @PostConstruct(可能依赖的 Bean 还没初始化完)。最稳妥、最常用、官方推荐的方式是使用 CommandLineRunner 或 ApplicationRunner。
优先用 CommandLineRunner 或 ApplicationRunner
这两个接口专为“Spring 容器完全启动后、应用对外提供服务前”这一时机设计。此时所有 Bean(包括 DataSource、RedisTemplate、Service、Mapper)都已创建并注入完毕,可安全调用。
-
CommandLineRunner:接收
String[] args,适合处理原始命令行参数(如java -jar app.jar --env=prod) -
ApplicationRunner:接收封装好的
ApplicationArguments,API 更友好,支持选项解析(如args.getOptionValues("config")) - 两者都支持
@Order或实现Ordered接口来控制多个初始化任务的执行顺序(例如:先建表结构,再插默认数据,最后预热缓存)
需要控制执行顺序?用 @Order 显式声明
当有多个初始化任务且存在依赖关系(比如 A 要往 Redis 写数据,B 要从 Redis 读数据),必须确保 A 在 B 之前运行。仅靠类名排序不可靠,应显式控制:
- 加
@Order(1)注解(数字越小越先执行) - 或让 Runner 类实现
Ordered接口,重写getOrder()方法返回整数 - 避免把不同职责的逻辑塞进同一个 Runner —— 拆成多个独立 Bean,便于复用和排序
其他方式对比:什么情况可以考虑?
@PostConstruct:适合单个 Bean 内部的轻量初始化(如初始化内部 Map、校验自身字段)。但它发生在 Bean 创建阶段,不保证其他 Bean 已就绪,跨 Bean 调用风险高,不适合数据库/缓存等外部资源操作。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
ApplicationReadyEvent 监听:监听 @EventListener(ApplicationReadyEvent.class),时机最晚(所有 Runner 执行完、应用真正就绪),适合做最终检查、发通知、启动外部守护线程等收尾动作,但一般不用来加载主业务数据。
静态代码块 / 构造方法:执行太早,此时 Spring 容器尚未介入,@Value、@Autowired 全无效,仅适用于纯 Java 静态配置或日志打点,不能用于业务初始化脚本。
一个典型初始化脚本示例
比如启动时加载系统字典到本地缓存:
@Component
@Order(1)
public class DictCacheLoader implements CommandLineRunner {
private final DictService dictService;
private final LocalCache localCache;
public DictCacheLoader(DictService dictService, LocalCache localCache) {
this.dictService = dictService;
this.localCache = localCache;
}
@Override
public void run(String... args) throws Exception {
List<Dict> all = dictService.findAll();
all.forEach(d -> localCache.put(d.getType(), d.getValue()));
System.out.println("✅ 字典缓存加载完成,共 " + all.size() + " 条");
}
}

















