Spring Boot 启动速度优化:你真确定慢的是“启动”吗?

举报
bug菌 发表于 2026/01/13 20:40:55 2026/01/13
【摘要】 🏆本文收录于《滚雪球学SpringBoot 3》:https://blog.csdn.net/weixin_43970743/category_12795608.html,专门攻坚指数提升,本年度国内最系统+最专业+最详细(永久更新)。  本专栏致力打造最硬核 SpringBoot3 从零基础到进阶系列学习内容,🚀均为全网独家首发,打造精品专栏,专栏持续更新中…欢迎大家订阅持续学习。...

🏆本文收录于《滚雪球学SpringBoot 3》:https://blog.csdn.net/weixin_43970743/category_12795608.html,专门攻坚指数提升,本年度国内最系统+最专业+最详细(永久更新)。
  
本专栏致力打造最硬核 SpringBoot3 从零基础到进阶系列学习内容,🚀均为全网独家首发,打造精品专栏,专栏持续更新中…欢迎大家订阅持续学习。 如果想快速定位学习,可以看这篇【SpringBoot3教程导航帖】https://blog.csdn.net/weixin_43970743/article/details/151115907,你想学习的都被收集在内,快速投入学习!!两不误。
  
若还想学习更多,可直接前往《滚雪球学SpringBoot(全版本合集)》:https://blog.csdn.net/weixin_43970743/category_11599389.html,涵盖SpringBoot所有版本教学文章。

演示环境说明:

  • 开发工具:IDEA 2021.3
  • JDK版本: JDK 17(推荐使用 JDK 17 或更高版本,因为 Spring Boot 3.x 系列要求 Java 17,Spring Boot 3.5.4 基于 Spring Framework 6.x 和 Jakarta EE 9,它们都要求至少 JDK 17。)
  • Spring Boot版本:3.5.4(于25年7月24日发布)
  • Maven版本:3.8.2 (或更高)
  • Gradle:(如果使用 Gradle 构建工具的话):推荐使用 Gradle 7.5 或更高版本,确保与 JDK 17 兼容。
  • 操作系统:Windows 11

1) 分析启动耗时:用 Actuator 的 startup 把“时间花在哪”揪出来

1.1 先别急着改代码:你得先知道慢在哪一段

Spring Boot 提供了 startup(应用启动)端点,可以拿到启动序列里的各个步骤耗时。它支持:

  • GET:获取启动步骤的快照
  • POST:从缓冲区“drain”(排空)并返回数据

而这个端点背后依赖的是 BufferingApplicationStartup:它会把启动步骤(steps)缓存在内存里,同时记录时间戳与耗时;缓存满了之后就不再记录新的步骤。
StartupEndpoint 本身就是用 BufferingApplicationStartup 来描述启动时间线的。

1.2 怎么开:最小配置(别把端点开一堆,先开你要的)

Actuator 端点需要“启用 + 暴露”才可用,这是 Boot 文档里反复强调的:端点只有在 enabled & exposed 时才算 available。

一个偏“保守又够用”的配置(示例):

management:
  endpoints:
    web:
      exposure:
        include: health,info,startup
  endpoint:
    startup:
      enabled: true

端点开到公网前请务必做访问控制(别把“启动细节”送给别人当情报😅)。端点访问控制/启用策略在 Boot 端点文档里有说明。

1.3 “Wait for startup”到底看什么?

你在 startup 时间线里会看到一堆 step(比如 bean 创建、条件评估、WebServer 初始化等)。做法很简单粗暴但有效:

  • 把 startup 数据导出来
  • 按耗时排序
  • 先处理前 3~5 个最慢 step(80/20 法则)

这里的核心心法:你要优化的是“最慢的那几段”,不是“所有段都微调 5ms”

2) Lazy Initialization:全局懒加载能救命,但它也会“把问题挪到运行时”😈

2.1 怎么开:spring.main.lazy-initialization=true

Spring Boot 官方文档明确写了:可以用 spring.main.lazy-initialization 开启懒初始化;也可以用 SpringApplication/SpringApplicationBuilder 的 API 方式开启。

spring:
  main:
    lazy-initialization: true

它的机制是:Bean 不是在启动时就全部实例化,而是“用到再创建”。Spring Framework 文档对 lazy-init 的定义也很直白:第一次被请求时才创建,而不是启动时就预实例化。

2.2 它的副作用:启动变快了,但“首个请求”可能变慢

Spring Boot 参考文档(老版本也明确指出这一点)提到:在 Web 应用里,开启 lazy init 会导致很多 Web 相关 bean 直到收到 HTTP 请求才初始化;缺点是它可能延迟暴露应用问题(启动时没报错,不代表运行时不会炸)。

我用更“人话”翻译一下:

  • ✅ 启动速度:通常能明显提升(尤其是 bean 多、自动配置多的项目)
  • ⚠️ 首次流量:可能出现“冷启动抖一下”(第一个请求触发一堆 bean 初始化)
  • ⚠️ 稳定性:某些配置/依赖问题不再在启动阶段暴露,而是在运行时才暴露(最讨厌这种😵‍💫)

2.3 更稳的用法:全局懒 + 关键 Bean 显式 eager

Boot 文档也说了:如果全局 lazy 了,但某些 bean 你想让它仍然 eager,可以用 @Lazy(false) 显式关闭该 bean 的懒加载。

import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

@Lazy(false) // 我就要你启动时创建
@Component
public class WarmupCriticalBean {
}

我的经验:

  • 网关/鉴权/路由表/DB连接池初始化这类“基础设施”,更适合 eager(不然第一个用户就替你踩坑了🥲)
  • 业务边角功能、后台任务、低频组件,更适合 lazy

3) 减少 Classpath 扫描范围:@ComponentScan 别扫全宇宙

启动慢的一大类根因就是:组件扫描扫描太广,尤其是把“根包”放得太顶,导致 classpath 里很多无关类都被扫描。

3.1 @ComponentScan 的官方规则:basePackages/basePackageClasses

Spring Framework 文档说明:你可以在 @ComponentScan 里用 basePackages 指定扫描包,或用 basePackageClasses 指定一个/多个“锚点类”来确定扫描范围。
@ComponentScan 的 Javadoc 也明确:basePackageClasses()basePackages() 用来定义要扫描的包;如果不指定,会从标注该注解的类所在包开始扫描。

3.2 实战建议:用 basePackageClasses 更不容易写错

因为字符串包名太容易拼错/改包名忘了改配置;用类当锚点就踏实很多。

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackageClasses = {
    com.myteam.app.Application.class,       // 主业务
    com.myteam.shared.SharedConfig.class    // 共享模块(可选)
})
public class Application {}

小吐槽:我见过有人 @ComponentScan("com")……嗯,启动慢是应该的🙂

3.3 更狠的方式:不扫组件,改成“显式导入”

Spring Boot 文档甚至给了一个思路:你可以让 @Component@ConfigurationProperties 不自动检测,改为显式 @Import 用户自定义 bean(属于“我知道我在干啥”的高级模式)。

这种方式适合:

  • 超大项目
  • 模块特别多
  • 想把启动路径变得极可控(但维护成本会上升)

4) 剔除无用的 AutoConfiguration:别让 Boot 给你“热心办坏事”

Spring Boot 官方文档说得非常明确:如果有你不想要的自动配置类生效,可以用 @SpringBootApplication(exclude=...) 禁用它。

4.1 方式一:@SpringBootApplication(exclude=...)

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class Application {}

Boot 文档就是这么示例的。

4.2 方式二:用属性 spring.autoconfigure.exclude

@EnableAutoConfiguration 的 Javadoc 也提到:除了 exclude()/excludeName(),你还可以通过 spring.autoconfigure.exclude 属性来排除自动配置。

spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

4.3 你该“剔除谁”?——不要靠猜,靠 startup/条件评估报告

建议顺序:

  1. startup 端点找耗时大户(谁初始化慢)
  2. 再看它来自哪个 auto-configuration(通常能沿着 bean 定义/自动配置类追到源头)
  3. 确认你确实不需要它(比如你根本不用 JDBC,却引入了会触发 DataSource 相关自动配置的依赖)
  4. 再 exclude

这里最容易犯的错:
“我觉得用不到就删” → 结果删掉的是别人依赖的基础设施 → 应用能启动但运行时坏得更隐蔽😇
所以我更推荐“先用 startup 数据排雷,再动刀”。

一套“我会这么干”的落地流程(不玄学版)✅

  1. 开 Actuator startup,抓一次启动数据(本地/测试环境都行)

  2. Top N 排序:先对最慢 3~5 个 step 下手

  3. 能靠配置解决的先配:

    • spring.main.lazy-initialization=true(再把关键 bean @Lazy(false) 拉回来)
  4. 扫描范围收紧:

    • @ComponentScan(basePackageClasses=...) 控制边界
  5. 排除无用自动配置:

    • excludespring.autoconfigure.exclude
  6. 再抓一次 startup 数据对比(你得看到“哪段变快了”,不然优化没闭环)

🧧福利赠与你🧧

  无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」,bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。

最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G PDF编程电子书、简历模板、技术文章Markdown文档等海量资料。

ps:本文涉及所有源代码,均已上传至Gitee:https://gitee.com/bugjun01/SpringBoot-demo 开源,供同学们一对一参考 Gitee传送门https://gitee.com/bugjun01/SpringBoot-demo,同时,原创开源不易,欢迎给个star🌟,想体验下被🌟的感jio,非常感谢❗

🫵 Who am I?

我是 bug菌:

  • 热活跃于 CSDN:https://blog.csdn.net/weixin_43970743 | 掘金:https://juejin.cn/user/695333581765240 | InfoQ:https://www.infoq.cn/profile/4F581734D60B28/publish | 51CTO:https://blog.51cto.com/u_15700751 | 华为云:https://bbs.huaweicloud.com/community/usersnew/id_1582617489455371 | 阿里云:https://developer.aliyun.com/profile/uolxikq5k3gke | 腾讯云:https://cloud.tencent.com/developer/user/10216480/articles 等技术社区;
  • CSDN 博客之星 Top30、华为云多年度十佳博主&卓越贡献奖、掘金多年度人气作者 Top40;
  • 掘金、InfoQ、51CTO 等平台签约及优质作者;
  • 全网粉丝累计 30w+

更多高质量技术内容及成长资料,可查看这个合集入口 👉 点击查看:https://bbs.csdn.net/topics/612438251 👈️
硬核技术公众号 「猿圈奇妙屋」https://bbs.csdn.net/topics/612438251 期待你的加入,一起进阶、一起打怪升级。

- End -

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。