283 lines
14 KiB
Markdown
283 lines
14 KiB
Markdown
# 一、启动流程
|
||

|
||
|
||
# 二、 阶段详解
|
||
## 2.1 SpringApplication初始化
|
||
**🔹 步骤1.1 - main方法入口执行**
|
||
- 执行位置:标注@SpringBootApplication的类中的main方法
|
||
- 核心动作:
|
||
1. 创建SpringApplication实例对象
|
||
2. 设置应用的基本配置信息
|
||
3. 准备启动所需的基础环境
|
||
|
||
  main方法是整个Spring Boot应用启动的唯一起点。当Java虚拟机开始执行程序时,首先会调用标注有@SpringBootApplication注解的主类中的main方法。在这个方法内部,会创建SpringApplication实例并调用其run方法,正式开启启动流程。
|
||
  SpringApplication的构造方法会进行一些重要的初始化工作,包括推断主配置类、设置初始引导类等。推断主配置类的过程是通过分析当前线程的堆栈信息来完成的,确保能够准确找到包含main方法的那个类。
|
||
|
||
**🔹 步骤1.2 - 加载SpringFactories配置**
|
||
- 配置源:META-INF/spring.factories文件
|
||
- 加载内容:
|
||
1. ApplicationContextInitializer(上下文初始化器)
|
||
2. ApplicationListener(应用监听器)
|
||
3. BeanFactoryPostProcessor(Bean工厂后处理器)
|
||
4. AutoConfigurationImportSelector(自动配置选择器)
|
||
|
||
  Spring Boot使用SpringFactoriesLoader机制从类路径下的**META-INF/spring.factories**文件中加载各种扩展组件。**这种机制是Spring Boot自动配置的核心基础,它允许框架和开发者通过标准的配置文件来注册和发现各种扩展实现。**
|
||
  配置文件中定义了多种类型的组件,包括**应用上下文初始化器、应用事件监听器、Bean工厂后处理器**等。这些组件将在后续的启动过程中按照特定的顺序被执行,共同完成应用的初始化工作。
|
||
|
||
**🔹 步骤1.3 - 推断Web应用类型**
|
||
- 检测逻辑:
|
||
1. 检查类路径是否存在Servlet相关类
|
||
2. 检查Spring MVC相关组件
|
||
3. 检查WebFlux相关组件
|
||
- 推断结果
|
||
🅰️ SERVLET:传统Web应用
|
||
🅱️ REACTIVE:响应式Web应用
|
||
©️ NONE:非Web应用
|
||
|
||
  应用类型推断是Spring Boot自动配置的重要环节。系统会根据项目的依赖情况自动判断应用类型,这直接影响后续创建的应用上下文类型和内嵌服务器的选择。
|
||
  **推断过程主要通过检查类路径中是否存在特定的类来完成。例如,如果存在Servlet相关的类,就推断为Web应用;如果存在WebFlux相关的类,就推断为响应式Web应用。** 这种基于类路径的自动推断机制使得开发者无需手动配置应用类型,大大简化了配置工作。
|
||
|
||
## 2.2 环境准备与配置加载
|
||
**🔹 步骤2.1 - 创建环境对象**
|
||
```
|
||
环境对象层次结构:
|
||
Environment(环境接口)
|
||
↓
|
||
ConfigurableEnvironment(可配置环境)
|
||
↓
|
||
具体环境实现(StandardEnvironment/StandardServletEnvironment)
|
||
├── PropertySources(属性源列表)
|
||
├── Profiles(激活的配置文件)
|
||
└── ConversionService(类型转换服务)
|
||
```
|
||
|
||
  环境对象是Spring Boot应用运行时的配置中心,它负责管理所有的配置属性和运行环境信息。根据应用类型的不同,Spring Boot会创建相应的环境实例。
|
||
  环境对象采用分层设计,提供了统一的属性访问接口,同时支持多种属性源的动态管理。环境对象还负责管理激活的配置文件(Profile),支持基于不同环境的配置隔离和切换。
|
||
|
||
**🔹 步骤2.2 - 配置属性源加载**
|
||
📊 属性源加载优先级(从高到低):
|
||
| 优先级 | 属性源类型 | 说明 |
|
||
| - | - | - |
|
||
| 1 | 命令行参数 | --spring.profiles.active=dev |
|
||
| 2 | Java系统属性 | System.getProperties() |
|
||
| 3 | 操作系统环境变量 | 系统级环境配置 |
|
||
| 4 | 应用配置文件 | application-{profile}.yml/properties |
|
||
| 5 | 默认属性 | SpringApplication.setDefaultProperties() |
|
||
|
||
  属性源加载遵循严格的优先级顺序,确保重要的配置能够覆盖默认配置。这种优先级设计使得配置管理更加灵活,开发者可以通过不同级别的配置来调整应用行为。
|
||
|
||
**🔹 步骤2.3 - Profile处理机制**
|
||
- Profile激活方式:
|
||
1. 通过spring.profiles.active显式指定
|
||
2. 通过spring.profiles.include包含其他profile
|
||
3. 默认使用default profile
|
||
- Profile解析流程:
|
||
1. 读取所有可用的profile配置
|
||
2. 解析条件化配置注解
|
||
3. 合并不同profile的配置项
|
||
4. 处理配置覆盖和冲突解决
|
||
|
||
  Profile机制是Spring框架提供的环境隔离解决方案,它允许开发者为不同的运行环境定义不同的配置。Spring Boot在启动时会根据激活的Profile来加载相应的配置,并处理配置之间的覆盖关系。
|
||
  Profile的激活可以通过多种方式实现,包括命令行参数、系统属性、配置文件等。系统支持同时激活多个Profile,并提供了灵活的配置合并策略来处理可能出现的配置冲突。
|
||
|
||
**🔹 步骤2.4 - 配置属性绑定**
|
||
1. 属性值解析:从各种属性源中获取属性值
|
||
2. 类型转换:将字符串值转换为目标类型
|
||
3. 数据验证:基于JSR-303进行数据校验
|
||
4. 对象绑定:将属性值设置到@ConfigurationProperties类
|
||
|
||
  配置属性绑定是将外部配置值注入到Java对象中的过程。Spring Boot提供了强大的属性绑定功能,支持宽松的绑定规则、类型转换、数据验证等特性。
|
||
  绑定过程首先会从环境对象中获取属性值,然后进行类型转换,将字符串类型的配置值转换为目标属性类型。如果配置了验证规则,还会执行数据验证,确保配置值的正确性。最后,将验证通过的属性值设置到目标对象中。
|
||
|
||
## 2.3 应用上下文创建与初始化
|
||
**🔹 步骤3.1 - 创建应用上下文实例**
|
||
📋 上下文类型映射表:
|
||
| 应用类型 | 上下文实现类 | 特点描述 |
|
||
| - | - | - |
|
||
| Web应用 | AnnotationConfigServletWebServerApplicationContext | 支持Servlet容器 |
|
||
| 响应式应用 | AnnotationConfigReactiveWebServerApplicationContext | 支持响应式编程 |
|
||
| 普通应用 | AnnotationConfigApplicationContext | 基础应用上下文 |
|
||
|
||
  应用上下文是Spring框架的核心容器,负责管理Bean的生命周期和依赖关系。Spring Boot会根据应用类型创建相应类型的应用上下文实例
|
||
|
||
**🔹 步骤3.2 - 应用上下文层次结构**
|
||
```
|
||
BeanFactory(Bean工厂基础接口)
|
||
↓
|
||
ApplicationContext(应用上下文接口)
|
||
↓
|
||
ConfigurableApplicationContext(可配置应用上下文)
|
||
↓
|
||
AbstractApplicationContext(抽象实现)
|
||
↓
|
||
GenericApplicationContext/AnnotationConfigApplicationContext
|
||
```
|
||
|
||
  应用上下文采用层次化设计,不同层次的接口和类承担不同的职责。这种设计使得上下文的功能可以逐步扩展,同时保持代码的清晰性和可维护性。
|
||
|
||
**🔹 步骤3.3 - 执行应用上下文初始化器**
|
||
- 执行时机:上下文创建后,Bean加载前
|
||
- 主要功能:
|
||
1. 🔧 注册自定义Bean定义
|
||
2. 🔧 设置上下文特定属性
|
||
3. 🔧 添加特殊的后处理器
|
||
4. 🔧 配置环境变量覆盖
|
||
|
||
  应用上下文初始化器是Spring Boot提供的重要扩展点,允许开发者**在上下文正式刷新之前执行自定义的初始化逻辑。** **初始化器可以通过spring.factories文件注册,也可以通过SpringApplication的addInitializers方法添加。**
|
||
  **初始化器的主要作用包括注册自定义的Bean定义、配置上下文特定的属性、添加特殊的后处理器等。** 通过初始化器,开发者可以深度定制应用上下文的行为,满足特殊的业务需求。
|
||
|
||
**🔹 步骤3.4 - 发布应用上下文事件**
|
||
事件发布序列:
|
||
1. ApplicationStartingEvent- 应用启动事件
|
||
2. ApplicationEnvironmentPreparedEvent- 环境准备完成事件
|
||
3. ApplicationContextInitializedEvent- 上下文初始化事件
|
||
4. ApplicationPreparedEvent- 应用准备事件
|
||
|
||
  Spring Boot的启动过程采用事件驱动模型,**每个关键步骤都会发布相应的事件**。这种设计使得各个模块之间解耦,同时也便于开发者通过监听事件来扩展启动逻辑。
|
||
|
||
## 2.4 Bean定义加载与处理
|
||
**🔹 步骤4.1 - Bean定义加载方式**
|
||
多种Bean定义加载途径:
|
||
1. 🔍 组件扫描:自动扫描@Component、@Service等注解
|
||
2. 📝 @Bean方法:处理@Configuration类中的@Bean方法
|
||
3. 📂 @Import导入:导入其他配置类
|
||
4. 🔗 ImportSelector:动态选择导入的配置类
|
||
|
||
  Bean定义加载是Spring容器初始化的核心环节。Spring Boot支持多种Bean定义加载方式,每种方式都有其适用的场景和特点。
|
||
|
||
**🔹 步骤4.2 - 组件扫描详细过程**
|
||
```
|
||
组件扫描流程:
|
||
开始扫描指定包路径
|
||
↓
|
||
读取包下的所有class文件
|
||
↓
|
||
解析类上的注解信息
|
||
↓
|
||
识别Spring组件注解
|
||
↓
|
||
注册Bean定义到容器
|
||
↓
|
||
完成组件扫描
|
||
```
|
||
|
||
  组件扫描是Spring Boot自动配置的基础机制,它能够自动发现和注册项目中的Spring组件。扫描过程基于注解元数据,通过反射机制分析类的结构信息。
|
||
|
||
**🔹 步骤4.3 - Bean工厂后处理**
|
||
| 后处理器 | 功能描述 | 执行时机 |
|
||
| - | - | - |
|
||
| ConfigurationClassPostProcessor | 处理@Configuration类 | Bean定义加载后 |
|
||
| PropertySourcesPlaceholderConfigurer | 处理属性占位符 | 属性解析阶段 |
|
||
| CustomScopeConfigurer | 注册自定义作用域 | 作用域配置阶段 |
|
||
|
||
  BeanFactoryPostProcessor是Spring框架的重要扩展点,允许在Bean实例化之前修改Bean定义信息。Spring Boot在启动过程中会执行多个内置的BeanFactoryPostProcessor。
|
||
|
||
## 2.5 Bean实例化与生命周期
|
||
**🔹 步骤5.1 - Bean实例化策略**
|
||
实例化顺序规则:
|
||
1. 🥇 BeanFactoryPostProcessor- 工厂后处理器最先实例化
|
||
2. 🥈 BeanPostProcessor- Bean后处理器其次实例化
|
||
3. 🥉 单例Bean- 按依赖顺序实例化普通Bean
|
||
4. 🏅 其他作用域Bean- 按需实例化
|
||
|
||
  Bean实例化遵循特定的顺序规则,确保依赖关系正确的Bean能够按正确的顺序创建。实例化过程采用懒加载和急切实例化相结合的策略。
|
||
|
||
**🔹 步骤5.2 - 依赖注入机制**
|
||
依赖注入的三种方式:
|
||
1. 🏗️ 构造器注入- 通过构造函数注入依赖
|
||
2. 🛠️ Setter注入- 通过setter方法注入依赖
|
||
3. 🎯 字段注入- 直接在字段上使用@Autowired注入
|
||
|
||
  依赖注入是Spring框架的核心特性,它通过自动装配机制将Bean之间的依赖关系解耦。Spring支持多种依赖注入方式,每种方式都有其适用的场景。
|
||
|
||
**🔹 步骤5.3 - Bean后处理流程**
|
||
```
|
||
Bean后处理序列:
|
||
Bean实例化
|
||
↓
|
||
执行BeanPostProcessor.postProcessBeforeInitialization
|
||
↓
|
||
执行@PostConstruct方法
|
||
↓
|
||
执行InitializingBean.afterPropertiesSet
|
||
↓
|
||
执行自定义init方法
|
||
↓
|
||
执行BeanPostProcessor.postProcessAfterInitialization
|
||
↓
|
||
Bean完全就绪
|
||
```
|
||
|
||
  BeanPostProcessor是Bean生命周期管理的重要扩展点,它允许在Bean初始化前后执行自定义逻辑。Spring Boot内置了多个BeanPostProcessor,用于处理各种注解和AOP代理。
|
||
|
||
**🔹 步骤5.4 - 循环依赖解决机制**
|
||
三级缓存解决方案:
|
||
1. 一级缓存:存放完全初始化完成的Bean
|
||
2. 二级缓存:存放早期暴露的Bean(已实例化但未初始化)
|
||
3. 三级缓存:存放Bean工厂,用于创建Bean的早期引用
|
||
|
||
  循环依赖是Spring容器需要解决的重要问题。Spring通过三级缓存机制来解决单例Bean的循环依赖问题,确保即使存在循环引用也能正确完成依赖注入。
|
||
|
||
## 2.6 Web服务器启动与配置
|
||
**🔹 步骤6.1 - 内嵌服务器选择策略**
|
||
服务器自动配置逻辑:
|
||
1. 检查类路径中的服务器依赖
|
||
2. 按优先级选择:Tomcat > Jetty > Undertow
|
||
3. 根据应用类型创建对应的Web服务器工厂
|
||
4. 配置服务器参数(端口、上下文路径等)
|
||
|
||
  Spring Boot支持多种内嵌服务器,包括Tomcat、Jetty和Undertow。服务器选择基于类路径中的依赖,采用特定的优先级规则。
|
||
|
||
**🔹 步骤6.2 - Servlet容器初始化**
|
||
1. 🎯 创建ServletContext(Servlet上下文)
|
||
2. 🎯 注册DispatcherServlet(前端控制器)
|
||
3. 🎯 配置字符编码过滤器
|
||
4. 🎯 设置会话管理配置
|
||
5. 🎯 启用静态资源服务
|
||
|
||
  Servlet容器初始化是Web应用启动的关键环节。Spring Boot会自动配置Servlet容器,并注册必要的Servlet、Filter和Listener。
|
||
|
||
**🔹 步骤6.3 - MVC组件自动配置**
|
||
自动配置的MVC组件:
|
||
1. HandlerMapping- 请求映射处理器
|
||
2. HandlerAdapter- 处理器适配器
|
||
3. ViewResolver- 视图解析器
|
||
4. MessageConverter- 消息转换器
|
||
5. Interceptor- 拦截器配置
|
||
|
||
  Spring Boot为Spring MVC提供了完整的自动配置,包括处理器映射、视图解析、消息转换等组件。这些组件基于约定大于配置的原则,提供了合理的默认值。
|
||
|
||
## 2.7 启动完成与后处理
|
||
**🔹 步骤7.1 - 启动事件发布序列**
|
||
```
|
||
ApplicationStartingEvent
|
||
↓
|
||
ApplicationEnvironmentPreparedEvent
|
||
↓
|
||
ApplicationContextInitializedEvent
|
||
↓
|
||
ApplicationPreparedEvent
|
||
↓
|
||
ContextRefreshedEvent
|
||
↓
|
||
ApplicationReadyEvent
|
||
```
|
||
|
||
  当所有的Bean实例化、依赖注入和初始化回调都执行完成后,Spring容器会发布ContextRefreshedEvent事件。这个事件标志着Spring IoC容器已经完全刷新并准备就绪。
|
||
|
||
**🔹 步骤7.2 - 命令行运行器执行**
|
||
运行器类型与特点:
|
||
| 运行器接口 | 执行方法 | 参数类型 | 使用场景 |
|
||
| - | - | - | - |
|
||
| ApplicationRunner | run(ApplicationArguments) | 封装的应用参数 | 需要丰富参数信息时 |
|
||
| CommandLineRunner | run(String... args) | 原始字符串参数 | 简单参数处理时 |
|
||
|
||
  Spring Boot会执行所有实现了ApplicationRunner或CommandLineRunner接口的Bean。
|
||
|
||
**🔹 步骤7.3 - 健康检查与指标收集**
|
||
启动后的监控机制:
|
||
1. ❤️ 健康检查:通过HealthIndicator监控应用健康状态
|
||
2. 📊 应用指标:通过Micrometer收集运行时指标
|
||
3. 🔔 事件监听:监控应用生命周期事件
|
||
4. 📝 日志记录:记录启动完成状态和耗时
|