一、Spring Boot核心定位
简化 Spring 开发,自动配置、内嵌服务器、Starter 依赖、生产级特性,约定大于配置。
二、Spring Boot核心知识
1. 启动流程(精简版)
Spring Boot 启动 = 准备环境 + 刷新容器 + 初始化组件 + 启动服务器
最核心步骤只有一个:refresh () 刷新容器(IoC、Bean、自动配置、AOP 全在这里)
具体启动流程:
(1) 执行启动类 main 方法,调用 SpringApplication.run();
(2) 构造 SpringApplication,判断 Web 类型,加载监听器与初始化器;
(3) 准备运行环境,加载配置文件、命令行参数;
(4) 创建并刷新 ApplicationContext 容器
resh() :扫描、创建、初始化 Bean,完成自动配置、AOP、事务;
(5) 启动内嵌 Tomcat/Undertow 服务器;
(6) 发布启动事件,应用就绪。
2. 自动配置原理
(1) 核心注解
@SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan
(2) 自动配置流程
① @EnableAutoConfiguration 开启自动配置
② 读取SPI文件:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
③ 加载所有自动配置类
④ 按条件注解判断是否生效:
@ConditionalOnClass:存在某个类@ConditionalOnBean:存在某个 Bean@ConditionalOnMissingBean:不存在才创建@ConditionalOnProperty:配置项满足
⑤ 满足条件则创建 Bean
3. 配置加载优先级
(1) 配置文件
application.yml/application.properties- 多环境:
application-dev.yml、test、prod
(2) 配置加载优先级
命令行参数 > 外部配置文件 > application.yml > bootstrap.yml(Cloud 专用)
(3) 配置绑定
@Value:直接取值@ConfigurationProperties:批量绑定前缀
4. SPI(Service Provider Interface,服务发现)机制
(1) SPI的核心作用
- 解耦 :不用硬编码
new实现类 - 可插拔:替换实现类只改配置,不改代码
- SpringBoot 自动配置底层就是 SPI
(2) Java 原生SPI
① 规则
- 接口:
com.xxx.service.MyService - 实现:
com.xxx.service.impl.MyServiceImpl - 配置文件路径(固定):META-INF/services/接口全限定名
② 使用方式
java
ServiceLoader<MyService> loader = ServiceLoader.load(MyService.class);
for (MyService service : loader) {
service.doSomething();
}
③ 缺点
- 一次性加载所有实现类(浪费资源)
- 不能按需获取
- 不支持排序、条件、过滤
(3) Spring SPI 机制(SpringBoot 自动配置核心)
① Spring 专用 SPI 路径 :
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
② 作用:
SpringBoot 启动时自动读取这个文件,加载里面的自动配置类 。这就是 @EnableAutoConfiguration 底层原理
③ Spring SPI 优势:
按需加载、支持条件注解 @Conditional、支持排序、自动装配
④ 除了 Spring Boot,还有哪些框架用 SPI?
凡是要做到可插拔、可扩展、自动加载的框架,几乎都用 SPI。例如:
- JDBC:加载数据库驱动;
- Dubbo:协议、负载均衡、序列化,自己增强了 SPI;
- MyBatis / MyBatis-Plus:插件、方言自动加载;
- Slf4j:发现日志实现;
- ShardingSphere、Seata、Sentinel 等分布式框架也大量使用
5. 常用的Starter
spring-boot-starter-web:Web 开发spring-boot-starter-data-redis:Redisspring-boot-starter-jdbc / mybatis:数据库spring-boot-starter-security:权限spring-boot-starter-actuator:监控
三、拓展知识
1. 自定义Spring Boot Starter并按需使用
(1) 命名用 xxx-spring-boot-starter 规范;
(2) 创建属性类 @ConfigurationProperties 绑定配置;
(3) 编写自动配置类,用 @Configuration + 条件注解类,并为@Bean定义业务类;
java
@Configuration
@ConditionalOnClass(SmsService.class) // 1. 有这个类才生效
@EnableConfigurationProperties(SmsProperties.class)
// 2. 配置文件开启才生效(核心按需开关)
@ConditionalOnProperty(prefix = "sms", name = "enabled", havingValue = "true")
public class SmsAutoConfiguration {
@Bean
// 3. 容器里没有才创建(允许用户自定义覆盖)
@ConditionalOnMissingBean
public SmsService smsService(SmsProperties properties) {
return new SmsService(properties);
}
}
(4) 在 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 注册配置类;
(5) 打包后其他项目引入依赖即可自动生效。
- 开启加载(默认)
java
sms:
enabled: true # 满足条件 → 自动创建 SmsService Bean
appId: 123
secret: abc
- 关闭加载(不加载 Bean)
java
sms:
enabled: false # 不满足条件 → 跳过,不加载
2. 减少Bean加载时间
Spring Boot 启动慢,90% 是 Bean 加载 / 实例化 / 初始化太慢 。减少Bean加载时间的整体思路是少加载、晚加载、异步加载、不加载无用 Bean。具体可以通过以下方式减少Bean的加载时间:
- 开启懒加载(最简单、最有效),用到时再初始化 Bean;
java
spring:
main:
lazy-initialization: true
- 排除不需要的自动配置,减少无用 Bean 加载,不加载数据库、消息队列等无用自动配置;
java
spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
- org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
- 缩小包扫描范围,不扫描无关包,只扫需要的包,跳过无用包、第三方包、测试包;
java
@ComponentScan(basePackages = "com.xxx.controller, com.xxx.service")
- 关闭循环引用(SpringBoot 2.7+),减少依赖检查耗时;
java
spring:
main:
allow-circular-references: false
- 异步初始化 Bean(高级优化),不阻塞主线程;
java
@Bean
@Async
public UserService userService() {
return new UserServiceImpl();
}
- 依赖优化,删除无用 Starter、排除无用 Jar、避免重复依赖
- 使用Spring Boot 加速工具 / 框架扩展
- Spring Boot Daemon 进程预热
- 阿里 Arthas 优化
- 云原生,如镜像预热、JVM 预热
3. 启动优化
- 开启全局懒加载,用到时再初始化 Bean;
- 排除不需要的自动配置,减少无用 Bean 加载;
- 缩小包扫描范围,避免全量扫描;
- 关闭循环依赖,减少依赖检查耗时;
- 慢初始化 Bean 异步化,不阻塞主线程;
- 替换为性能更高的 Undertow 容器;
- 裁剪依赖、禁用 JMX、关闭无用监控;
- 高阶方案:分层启动、进程预热、GraalVM 原生镜像
4. 定位哪个 Bean 初始化最慢(Actuator / 启动日志分析)
开启启动分析报告:
logging:
level:
org.springframework.context.annotation: DEBUG
或使用:
- Spring Boot Actuator
- StartupEndpoint
- Arthas 分析方法耗时
5. 启动链路分析
启动链分析 = 追踪 Spring Boot 从 run () 到服务启动全过程的耗时与步骤 目的:定位慢 Bean、慢配置、慢初始化、阻塞点,精准优化启动速度。
(1) 4 种最实用的启动链分析方法
a、开启spring.main.log-startup-info 打印启动耗时报告(最简单,零侵入):打印所有 Bean 初始化耗时排序
spring:
main:
log-startup-info: true # 打印启动信息
logging:
level:
# 开启启动耗时统计(关键!)
org.springframework.boot.StartupInfoLogger: INFO
org.springframework.context: DEBUG
打印效果:
- 列出初始化最慢的 Bean
- 显示每个 Bean 构造、依赖注入、初始化耗时
- 直接定位慢 Bean
b、使用 Actuator 端点(最专业,可视化),查看完整启动时间线与阶段耗时
步骤①:引入 Actuator
XML
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
步骤②:开启配置
XML
management:
endpoints:
web:
exposure:
include: startup
endpoint:
startup:
enabled: true
步骤③:访问查看完整启动时间线
如:http://localhost:port/actuator/startup
能看到:
- 启动阶段耗时(refresh、onRefresh、createBean...)
- 每个 Bean 生命周期时间
- 精准定位阻塞步骤
c、使用 JVM 调试 / Arthas 追踪(生产环境神器)
①启动时打印堆栈:java -jar app.jar --debug
②Arthas 追踪启动方法:
bash命令 trace org.springframework.context.support.AbstractApplicationContext refresh
d、 启动日志关键阶段拆分,重点排查 refreshContext 阶段
Spring 启动核心流程 = 5 个阶段:
① prepareEnvironment:配置加载
② prepareContext:上下文准备
③ refreshContext(最核心):Bean 加载、自动配置
④ onRefresh:内嵌容器启动
⑤ finishRefresh:完成启动
90% 慢启动都卡在 refreshContext。
e、定位慢 Bean、慢配置、阻塞初始化后针对性优化
(2) 启动链分析能定位哪些问题
- 哪个 Bean 初始化最慢(连接池、第三方 SDK、Feign 等)
- 自动配置加载过多
- 循环依赖导致耗时高
- Bean 依赖过深、层级复杂
- @PostConstruct 里执行慢逻辑
- MyBatis、Redis、MQ 启动时建立连接阻塞