← 每日面试题 学习看板

如何在Spring启动过程中做缓存预热

面试题/00java/04 框架/01Spring/08扩展与最佳实践/如何在Spring启动过程中做缓存预热.md

面试记录 2026-10-27(Round 29)

题目:如何在 Spring 启动过程中做缓存预热?

难度:difficulty/medium

评分:⭐⭐⭐⭐☆(4/5)

我的回答

启动过程中进行预热可以使用 CommandLineRunner 接口,实现该接口,可以在所有 bean 实例化后初始化完成后执行,可以定义一些自定义操作,比如我们要做的缓存预热,还有类似的 ApplicationRunner。

点评

优点:CommandLineRunner/ApplicationRunner 时机准确(bean 实例化后、容器就绪前)。

不足:漏两 Runner 差异(ApplicationRunner 接收 ApplicationArguments,CommandLineRunner 接收 String[] args);漏 @PostConstruct、ApplicationReadyEvent、InitializingBean 备选。

补充:预热失败处理与启动耗时影响;SmartLifecycle 的 phase 控制。


完整讲解(权威版)

最后更新:2026-10-27 · 基于第 1 次作答

L1 · 30 秒速记

结论:缓存预热选 ApplicationRunner/CommandLineRunner,所有 Bean 就绪后、对外服务前执行。 关键词:Bean 就绪 · run() 完成前 · @Order 排序 边界:预热要幂等容错,失败不阻断启动。

L2 · 核心讲解

核心考点定位:考察 Spring 启动生命周期钩子,选对预热时机。面试官想排除"用 @PostConstruct 预热"的时机错误。

机制链(≥3 环):

  1. Bean 实例化 → @PostConstruct 执行:为什么——Bean 级,可能依赖未就绪,时机过早
  2. 容器刷新完成 → ContextRefreshedEvent:为什么——所有 Bean 已就绪,但应用可能未对外
  3. SpringApplication.run() 完成前 → Runner 执行:为什么——最安全,所有 Bean 就绪且即将对外服务

证据锚点(≥10):

对比与权衡:

时机正确性依赖就绪适用
@PostConstruct中部分 BeanBean 内初始化
ContextRefreshedEvent高全 Bean容器级预热
ApplicationRunner高全 Bean+环境缓存预热(推荐)
ApplicationReadyEvent高全部就绪对外后预热

常见误区:

  1. 错误:用 @PostConstruct 预热缓存 → 正确:用 ApplicationRunner → 为什么:@PostConstruct 时部分 Bean 未就绪,缓存依赖可能拿不到
  2. 错误:Runner 失败会静默 → 正确:抛异常会导致启动失败 → 为什么:需 try-catch 容错,记录日志
  3. 错误:预热越多越好 → 正确:控制耗时 → 为什么:阻塞启动,大缓存需异步/分批
  4. 错误:CommandLineRunner 和 ApplicationRunner 一样 → 正确:参数类型不同 → 为什么:前者 String[] args,后者 ApplicationArguments

适用边界:Runner 是启动一次性动作;运行时缓存更新靠定时任务或事件监听,不能只靠启动预热。大缓存预热要异步或分批,避免拖慢启动。若应用是集群部署,预热还要考虑多实例同时预热对下游 DB 的冲击,必要时用预热锁或错峰。

延伸追问(≥3)

  1. @PostConstruct 和 ApplicationRunner 哪个先?
  1. 预热失败会怎样?
  1. 多个 Runner 如何控制顺序?

面试者参考回答(400–700 字)

【结论】 面试官您好,缓存预热我选 ApplicationRunner/CommandLineRunner,它们在所有 Bean 就绪后、应用对外服务前执行。

【三点】 第一,时机——@PostConstruct 是 Bean 级,此时其他 Bean 可能未就绪;Runner 在 SpringApplication.run() 完成前执行,所有 Bean 已就绪,最安全。第二,两者区别——CommandLineRunner 收 String[] args,ApplicationRunner 收解析后的 ApplicationArguments,可用 @Order 控制顺序。第三,实践——预热要幂等容错(失败记日志不阻断启动),大缓存异步或分批控制耗时,避免拖慢启动。

【边界】 当然,预热是启动时一次性动作,运行时缓存更新还得靠定时任务或监听变更事件,不能只靠启动预热。


作答历史

#日期评分本轮主要问题记录
12026-10-274/5漏两 Runner 差异与备选时机第 1 次