CommandLineRunner 是最常用轻量的启动初始化方式,容器初始化完毕后、应用就绪前执行,适合数据预热等;实现接口并用 @Component 注册即可,支持 @Order 控制多任务顺序,但需避免阻塞和未捕获异常。

直接用 CommandLineRunner 接口是最常用、最轻量的方式——它在 Spring 容器完全初始化完毕后、应用正式就绪前执行,适合做数据预热、资源加载、配置校验等操作。
怎么写一个 CommandLineRunner
只需定义一个类,实现 CommandLineRunner 接口,并重写 run(String... args) 方法,再用 @Component 注册为 Spring Bean 即可:
- Spring Boot 启动流程走到最后阶段(所有 Bean 加载完成、内嵌容器已启动但尚未对外提供服务)时,会自动调用所有
CommandLineRunner实例的run方法 - 方法参数是原始命令行字符串数组,比如启动时执行
java -jar app.jar --env=prod --port=8081,那么args就是["--env=prod", "--port=8081"] - 若需解析参数(如提取
--env的值),建议改用ApplicationRunner;若只是简单执行、不依赖参数结构,CommandLineRunner更直观
多个初始化任务怎么控制顺序
当项目里有多个初始化逻辑(比如先建缓存、再刷数据、最后发通知),可以用 @Order 注解明确执行优先级:
-
@Order(1)表示最高优先级,数值越小越早执行 - 不同
CommandLineRunner实现类之间共享同一套排序规则,@Order(1)和@Order(2)的类会严格按序执行 - 未加
@Order的默认顺序靠后(等效于@Order(Integer.MAX_VALUE))
常见使用场景和注意事项
它不是万能“启动钩子”,要注意边界和风险:
立即学习“Java免费学习笔记(深入)”;
- 可以安全注入其他 Bean(如
Repository、Service),因为此时依赖注入已完成 - 如果
run()方法抛出未捕获异常,整个应用启动会失败——务必对关键操作做 try-catch 或声明式容错 - 避免耗时过长的操作(如同步拉取远程大文件),否则会阻塞应用就绪;如需异步,可用
@Async+ 线程池,但要确保线程池已初始化 - 不适合做“容器启动前”的事(比如修改
ApplicationContext配置),那得用ApplicationContextInitializer或SpringApplicationRunListener
一个实用的例子
比如启动时往内存 Map 中加载基础字典数据:
- 定义
DataCache工具类,含静态Map<string string></string> - 写一个
@Component @Order(10)类实现CommandLineRunner - 在
run方法中调用dataRepository.findAll(),遍历结果并存入DataCache - 后续业务代码直接通过
DataCache.get("status_1")获取,无需重复查库


















