1. 初始化 SpringApplication
├── 设置主类、推断应用类型(Web/非 Web)
├── 加载初始化器(ApplicationContextInitializer)和监听器(ApplicationListener)
└── 加载 Bootstrapper 和事件监听器(通过 SPI 机制)
2. 准备环境(Environment)
├── 加载 `application.properties`/`application.yml` 配置文件
├── 解析命令行参数
└── 构建 `ConfigurableEnvironment` 对象
3. 创建应用上下文(ApplicationContext)
├── 根据应用类型选择实现类(如 `AnnotationConfigServletWebServerApplicationContext`)
└── 通过反射实例化上下文对象
4. 刷新应用上下文(Refresh Context)
├── 加载 Bean 定义
│ ├── 扫描 `@Component`、`@Bean` 等注解类
│ └── 解析配置类并注册 BeanDefinition
├── 调用 `BeanFactoryPostProcessor`
│ ├── 修改 Bean 定义(如占位符替换)
│ └── 处理 `@Configuration` 类
├── 注册 `BeanPostProcessor`
│ ├── 如 `AutowiredAnnotationBeanPostProcessor`(处理 `@Autowired`)
│ └── 如 `CommonAnnotationBeanPostProcessor`(处理 `@PostConstruct`)
├── 初始化单例 Bean
│ ├── 实例化 Bean → **将工厂对象存入三级缓存(singletonFactories)**
│ ├── 填充属性(依赖注入)
│ │ ├── 若发生循环依赖 → **从三级缓存获取工厂生成早期引用(存入二级缓存)**
│ │ └── 递归触发依赖 Bean 的初始化
│ ├── 调用 Aware 接口(如 `BeanNameAware`)
│ ├── `BeanPostProcessor.postProcessBeforeInitialization()`(如 AOP 代理)
│ ├── 执行初始化方法(`@PostConstruct`、`InitializingBean`)
│ └── `BeanPostProcessor.postProcessAfterInitialization()` → **存入一级缓存(singletonObjects)**
└── 发布 `ContextRefreshedEvent` 事件
5. 启动内嵌服务器(Web 应用)
├── 创建 `WebServer`(如 Tomcat)并绑定端口
└── 注册 `DispatcherServlet`
6. 调用 `CommandLineRunner` 和 `ApplicationRunner`
├── 按 `@Order` 优先级执行自定义启动逻辑
└── 发布 `ApplicationReadyEvent`
7. 应用运行
├── 处理 HTTP 请求(通过 `DispatcherServlet`)
└── 执行后台任务(如定时任务)
8. 接收关闭信号(如 `SIGTERM` 或 `SpringApplication.exit()`)
9. 发布 `ContextClosedEvent`
10. 销毁 Bean
├── 调用 `@PreDestroy` 方法
└── 调用 `DisposableBean.destroy()`
11. 关闭内嵌服务器(释放端口)
以下是为Spring Boot启动流程各步骤增加的详细说明和解释(引用知识库内容增强说明):
1. 初始化 SpringApplication
- 主类设置:记录启动类
@SpringBootApplication
标注的类,作为组件扫描的起点[[6]]。 - 应用类型推断:通过类路径检测(如存在Tomcat依赖则标记为Web应用),决定使用
AnnotationConfigServletWebServerApplicationContext
等上下文实现[[10]]。 - 初始化器加载:通过
spring.factories
机制加载ApplicationContextInitializer
,用于在容器刷新前修改配置[[6]]。 - 监听器注册:加载
ApplicationListener
实现类,统一由EventPublishingRunListener
管理事件广播[[10]]。
2. 准备环境(Environment)
- 配置文件加载:按优先级从
classpath:/config
、classpath:/
、当前目录等位置加载application.properties/yml
[[8]]。 - 命令行参数绑定:将
--key=value
格式的参数转换为PropertySource
,优先级高于文件配置[[8]]。 - 环境对象构建:创建
StandardServletEnvironment
(Web应用),整合系统属性、环境变量、配置文件等属性源[[6]]。
3. 创建应用上下文
- 上下文类型选择:根据应用类型选择
AnnotationConfigServletWebServerApplicationContext
(Web)或AnnotationConfigApplicationContext
(非Web)[[10]]。 - 反射实例化:通过无参构造函数创建上下文对象,初始化
AnnotatedBeanDefinitionReader
和ClassPathBeanDefinitionScanner
[[6]]。
4. 刷新应用上下文(核心阶段)
4.1 加载Bean定义
- 组件扫描:从主类所在包递归扫描
@Component
、@Service
等注解类[[8]]。 - 配置类解析:通过
ConfigurationClassPostProcessor
处理@Configuration
类,注册@Bean
方法为BeanDefinition
[[10]]。
4.2 调用BeanFactoryPostProcessor
- 占位符替换:
PropertySourcesPlaceholderConfigurer
解析${}
占位符,替换为环境变量值[[6]]。 - 配置类增强:为
@Configuration
类生成CGLIB代理,确保@Bean
方法在Spring上下文中执行[[10]]。
4.3 注册BeanPostProcessor
- 依赖注入处理器:注册
AutowiredAnnotationBeanPostProcessor
处理@Autowired
和@Value
[[6]]。 - 生命周期处理器:注册
CommonAnnotationBeanPostProcessor
处理@PostConstruct
和@PreDestroy
[[10]]。
4.4 初始化单例Bean
- 三级缓存机制:
- 一级缓存(singletonObjects):存储完全初始化的Bean。
- 二级缓存(earlySingletonObjects):存储早期暴露的Bean引用。
- 三级缓存(singletonFactories):存储
ObjectFactory
,用于生成代理对象(解决AOP循环依赖)[[6]]。
- 循环依赖处理:通过三级缓存提前暴露工厂对象,生成代理解决setter循环依赖[[10]]。
- 初始化流程:
- 实例化Bean(构造函数调用)。
- 填充属性(依赖注入,递归初始化依赖Bean)。
- 调用
BeanNameAware
等Aware接口。 - 执行
BeanPostProcessor
前置处理(如AOP代理)。 - 调用
@PostConstruct
和afterPropertiesSet()
。 - 执行
BeanPostProcessor
后置处理。 - 存入一级缓存[[6]][[10]]。
4.5 发布事件
- ContextRefreshedEvent:通知监听器容器已刷新完成,常用于启动后台任务[[10]]。
5. 启动内嵌服务器(Web应用)
- WebServer创建:通过
TomcatServletWebServerFactory
创建Tomcat实例,绑定配置的端口(支持SSL和随机端口)[[8]]。 - DispatcherServlet注册:将Spring MVC前端控制器映射到
/
路径,处理所有HTTP请求[[10]]。
6. 调用Runner接口
- 执行顺序:按
@Order
排序,ApplicationRunner
优先于CommandLineRunner
执行[[6]]。 - 异常处理:任一Runner失败则终止应用启动,可通过try-catch捕获异常[[6]]。
7. 应用运行
- 请求处理:
DispatcherServlet
通过HandlerMapping
查找控制器,HandlerAdapter
执行方法,ViewResolver
渲染视图[[10]]。 - 定时任务:通过
@Scheduled
注解触发,由ScheduledTaskRegistrar
管理线程池[[10]]。
8. 接收关闭信号
- ShutdownHook注册:默认添加JVM关闭钩子,捕获
SIGTERM
或SIGINT
信号[[6]]。 - 优雅关闭:停止接收新请求,等待活动请求完成(可配置超时时间)[[10]]。
9. 发布ContextClosedEvent
- 事件触发:在销毁Bean前发布,用于释放数据库连接等资源[[10]]。
10. 销毁Bean
- 销毁方法调用:按
@PreDestroy
→DisposableBean.destroy()
→ 自定义destroy-method
顺序执行[[6]]。
11. 关闭内嵌服务器
- 资源释放:关闭Tomcat/Jetty服务器,释放端口和连接池资源[[8]]。