Spring Boot 启动太慢?一文彻底搞懂启动流程+提速大法!
ubuntu 20.04 LTS 更换阿里云源第一步:先备份下原始源:sudo cp /etc/apt/source.list /etc/apt/source.list.backup第二步:修改文件vim /etc/apt/source.list清除原有的,替换以下源复制代码deb http://mirrors.aliyun.com/ubuntu/ focal main restricteddeb
在日常开发中,你是否遇到过这样的场景:
“为什么我这个 Spring Boot 项目启动要十几秒,甚至几十秒?”
“别人同样的依赖和功能,启动速度就是比我快?”
“如何排查和优化启动过程,让开发体验更顺畅?”
本篇文章将从 启动流程解析 入手,结合实际开发中常见的 启动慢原因分析,提供 实用的加速技巧,帮助你彻底搞懂 Spring Boot 启动慢的底层原因,做到“对症下药”。
一、Spring Boot 启动流程简析
Spring Boot 应用的启动是通过调用 SpringApplication.run(...)
方法完成的,其背后大致可以分为以下几个阶段:
1. 准备阶段
-
设置默认属性
-
加载 SpringApplicationRunListeners(监听器)
-
准备环境(Environment)
-
打印 Banner
-
创建 ApplicationContext
2. 上下文初始化阶段
-
初始化 ApplicationContext
-
调用 ApplicationContextInitializer
-
注册 Bean 定义
-
执行 BeanFactoryPostProcessor
-
执行 BeanPostProcessor
3. 应用启动阶段
-
启动内嵌 Web 容器(Tomcat/Jetty)
-
执行 ApplicationRunner / CommandLineRunner 接口
-
监听器回调:ApplicationStartedEvent / ApplicationReadyEvent
二、常见导致 Spring Boot 启动慢的原因
Spring Boot 虽然已经做了大量优化,但项目规模一旦增大或依赖不合理,仍然容易启动缓慢,以下是常见原因:
1. 引入了过多的 Starter 或未使用的依赖
例如:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
如果你引入了如上依赖,却未真正使用 Elasticsearch,会在启动阶段加载并初始化对应 Bean,浪费时间。
✅ 解决方法:
-
精简依赖,只引入真正用到的 starter。
-
使用
spring.factories
分析自动装配组件。
2. Bean 初始化过重或初始化时执行逻辑复杂
-
Bean 中执行了较耗时的逻辑(如连接远程服务、读取大文件等)。
-
使用了
@PostConstruct
执行初始化逻辑。
✅ 解决方法:
-
将部分初始化逻辑异步处理。
-
尽量延迟 Bean 的初始化(懒加载)。
3. 自动装配过多,组件扫描范围过大
例如在 @SpringBootApplication
使用默认的包扫描,导致项目中所有子包甚至工具包下的类都被扫描,拖慢启动速度。
✅ 解决方法:
@SpringBootApplication(scanBasePackages = {"com.example.app"})
精准指定包路径,避免无关类被扫描为 Bean。
4. 数据库连接与校验耗时
-
Spring Boot 默认会尝试连接数据库进行验证。
-
有些数据库连接超时设置不合理,连接池初始化缓慢。
✅ 解决方法:
-
开发环境可关闭数据库自动校验:
spring:
datasource:
initialization-mode: never
-
或使用
spring.sql.init.mode=never
5. 日志系统初始化缓慢
-
默认使用 Logback,可能因为日志配置文件复杂、文件写入缓慢导致启动卡顿。
✅ 解决方法:
-
简化日志配置。
-
本地开发时使用控制台输出,避免写入文件。
6. 文件扫描与资源加载耗时
-
如加载 classpath 下的大量静态资源(
.jar
,.yml
,.xml
等) -
Spring Boot 会自动加载所有
META-INF/spring.factories
,可能导致不必要的初始化。
✅ 解决方法:
-
移除未使用的依赖。
-
配置排除不需要的自动装配类。
三、加速 Spring Boot 启动的实用技巧
1. 启用懒加载(Spring Boot 2.2+ 支持)
懒加载可以避免启动时立即实例化所有 Bean,仅在第一次使用时加载。
spring:
main:
lazy-initialization: true
⚠️ 注意:某些依赖注入逻辑可能受影响,需测试评估是否适用。
2. 开启并行类加载(实验性)
对于大型项目,Spring 5+ 支持并行类加载。
System.setProperty("spring.backgroundpreinitializer.ignore", "false");
或使用环境变量设置 JVM 参数。
3. 使用 Spring Boot 3 + GraalVM Native Image
GraalVM Native Image 可将 Java 应用编译为原生二进制文件,启动速度提升几十倍,适合极端性能场景。
-
优点:启动速度毫秒级、内存占用小
-
缺点:编译慢、可用性和兼容性要求高
4. 分析启动性能:使用 spring-boot-actuator
+ StartupStep
Spring Boot 2.4+ 提供了 ApplicationStartup
,用于追踪 Bean 初始化等信息。
SpringApplication app = new SpringApplication(MyApp.class);
app.setApplicationStartup(new BufferingApplicationStartup(2048));
配合 actuator 可以看到每个步骤耗时。
5. 禁用无关功能
例如关闭 Banner、禁用自动热部署:
SpringApplication app = new SpringApplication(MyApp.class);
app.setBannerMode(Banner.Mode.OFF);
四、总结建议
问题 |
原因 |
优化建议 |
---|---|---|
启动慢 |
依赖过多 |
精简 starter |
Bean 初始化慢 |
执行逻辑复杂 |
懒加载 / 异步 |
包扫描多 |
范围太广 |
指定扫描路径 |
连接慢 |
数据库或远程资源 |
异步连接 / 延迟加载 |
日志慢 |
写入文件耗时 |
控制台输出 |
五、开发中的最佳实践
-
本地开发和生产环境的配置分离(使用 profile)
-
使用 Docker 构建镜像时避免构建期初始化数据库
-
每次新增依赖,检查其是否引入了不必要的 transitive 依赖
-
使用 JDK 17+ 可获得更好的启动性能(相比 JDK8)
🧩写在最后
Spring Boot 的启动慢,不是框架本身的问题,而是随着项目复杂度增加,各种组件组合在一起,导致启动过程越来越臃肿。 只要掌握启动流程原理,对症下药,就可以显著提高开发效率和本地调试体验。
下一篇我们将深入分析:Spring Boot 多环境配置实战:dev、test、prod 如何优雅切换?欢迎关注~
如果你觉得这篇文章有帮助,欢迎点赞、分享、收藏 🙌
更多推荐
所有评论(0)