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