SpringBoot启动太慢?几个优化技巧
项目越做越大,SpringBoot启动时间从几秒变成了30多秒。
改一行代码等半分钟,效率太低了。今天分享几个优化技巧,亲测有效。
先找到慢在哪
优化之前,先看看时间花在哪了。
SpringBoot 2.4以上可以开启启动分析:
@SpringBootApplicationpublicclassApplication{publicstaticvoidmain(String[]args){SpringApplicationapp=newSpringApplication(Application.class);app.setApplicationStartup(newBufferingApplicationStartup(2048));app.run(args);}}启动后访问/actuator/startup就能看到每个步骤的耗时。
常见的耗时大户:
- 包扫描范围太大
- 自动配置太多
- 数据源初始化
- MyBatis Mapper扫描
优化1:缩小包扫描范围
// 优化前:扫描整个包@SpringBootApplicationpublicclassApplication{}// 优化后:只扫描需要的包@SpringBootApplication(scanBasePackages={"com.example.controller","com.example.service","com.example.config"})publicclassApplication{}包越少,扫描越快。
优化2:排除不需要的自动配置
SpringBoot会自动配置很多东西,但不是都用得上:
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class,// 不用数据库时RedisAutoConfiguration.class,// 不用Redis时MongoAutoConfiguration.class,// 不用MongoDB时})publicclassApplication{}或者在配置文件里排除:
spring:autoconfigure:exclude:-org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration优化3:延迟初始化
spring:main:lazy-initialization:trueBean在第一次使用时才初始化,不是启动时全部初始化。
注意:第一次请求会变慢,生产环境慎用,开发环境很适合。
优化4:优化MyBatis配置
mybatis:configuration:lazy-loading-enabled:truemapper-locations:classpath:mapper/*.xml# 精确指定,不要用**Mapper接口用@Mapper注解代替包扫描:
// 不推荐@MapperScan("com.example")// 推荐@MapperpublicinterfaceUserMapper{}优化5:关闭开发环境不需要的功能
spring:profiles:active:dev---spring:config:activate:on-profile:dev# 开发环境关闭一些功能springdoc:api-docs:enabled:falsemanagement:endpoint:health:show-details:never优化6:JVM参数
开发环境追求启动快,可以加这些参数:
java -XX:TieredStopAtLevel=1\-noverify\-Dspring.jmx.enabled=false\-jar app.jar-XX:TieredStopAtLevel=1只用C1编译,启动更快-noverify跳过字节码验证-Dspring.jmx.enabled=false关闭JMX
大约能提升20%左右。
优化7:使用DevTools热重载
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope></dependency>改代码后不用完全重启,只重新加载变化的部分,几秒就能生效。
优化效果
| 优化项 | 优化前 | 优化后 |
|---|---|---|
| 缩小包扫描 | 30s | 27s |
| 排除自动配置 | 27s | 20s |
| 延迟初始化 | 20s | 12s |
| JVM参数 | 12s | 10s |
| DevTools | 10s | 3s |
从30秒到3秒,效率提升10倍。
开发vs生产
开发环境:追求启动快
spring:main:lazy-initialization:true生产环境:追求运行时性能
spring:main:lazy-initialization:false可以用不同的配置文件区分。
远程调试
有时候需要连测试环境的数据库调试,本地配置改成测试环境的地址就行:
spring:datasource:url:jdbc:mysql://测试环境IP:3306/testdb我用星空组网把本地电脑和测试环境连起来,配置文件写虚拟IP就能直接连,不用部署到服务器上调试,启动优化效果也能立刻验证。
小结
启动优化的核心思路:少加载、晚加载
- 缩小包扫描范围
- 排除不需要的自动配置
- 延迟初始化(开发环境)
- 用DevTools热重载
- JVM用快速启动参数
先从最简单的开始试,效果立竿见影。
有问题评论区交流~