1.自动配置的原理

springBoot项目都会有一个启动类,启动类上有一个@SpringBootApplicaion注解,这个注解是一个组合注解,主要有三部分组成:

spring boot 自动部署系统 spring boot自动配置原理_spring boot 自动部署系统


1、@SpringBootConfiguration

2、@EnableAutoConfiguration

3、@CompoentScan

其中,第一个注解表明了这个启动类是一个配置类,唯一特殊的是这个配置类有且只能有一个

第三个注解:扫描启动类所在的包以及子包下的所有标记为Bean或者派生注解的组件扫描并注册到IOC容器中

springBoot完成自动配置最关键的是依靠第二个注解@EnableAutoConfiguration

 
我们来看一下@EnableAutoConfiguration注解
这个注解也是一个注解.里面有两个主要注解:

spring boot 自动部署系统 spring boot自动配置原理_spring boot_02


1、@AutoConfigurationPackage

2、@Import(AutoConfigurationImportSelector.class):这个注解导入了AutoConfigurationImportSelector这个类,这个类会扫描类路径下的spring.factories文件。

AutoConfigurationImportSelector这个类会调用selectImports方法返回所有需要被注册为bean的类的全名的String[]数组集合,

 

**为什么不使用 @Import 直接引入自动配置类**

有两个原因:
1. 让主配置类和自动配置类变成了强耦合,主配置类不应该知道有哪些从属配置
2. 直接用 `@Import(自动配置类.class)`,引入的配置解析优先级较高,自动配置类的解析应该在主配置没提供时作为默认配置。

springBoot启动过程

我们可以看到启动类里面只有一个静态方法run

spring boot 自动部署系统 spring boot自动配置原理_spring boot 自动部署系统_03

 点进这个run方法

spring boot 自动部署系统 spring boot自动配置原理_spring boot_04

发现还是个run方法,我们再点进去

spring boot 自动部署系统 spring boot自动配置原理_spring_05

 啊,可以发现分为了两个步骤,一个是新建一个SpringApplication对象,另一个步骤是调用这个对象的成员方法run(), 注意,这里是成员方法,并不是启动类里的静态方法。 

下面我们来看一下主要的步骤:
阶段一:SpringApplication 构造

1. 记录 BeanDefinition 源

        这一步是从系统中到处寻找需要加入到IOC,也就是被spring管理的bean的定义信息。
2. 推断应用类型

        看看程序是什么类型的,比如非web程序,基于servlet的web程序,基于reactive的web程序
3. 记录 ApplicationContext 初始化器

        不少人可能会问:初始化器有什么作用呢?

        初始化器的作用是当需要对spring容器进行扩展功能时,需要初始化器提供必要的支持。
4. 记录监听器
5. 推断主启动类

阶段二:执行 run 方法

1. 得到 SpringApplicationRunListeners,名字取得不好,实际是事件发布器

   * 发布 application starting 事件1️
2. 封装启动 args
3. 准备 Environment 添加命令行参数(*)
4. ConfigurationPropertySources 处理(*)
   * 发布 application environment 已准备事件2️
5. 通过 EnvironmentPostProcessorApplicationListener 进行 env 后处理(*)
   * application.properties,由 StandardConfigDataLocationResolver 解析
   * spring.application.json
6. 绑定 spring.main 到 SpringApplication 对象(*)
7. 打印 banner(*)
8. 创建容器
9. 准备容器
   * 发布 application context 已初始化事件3️
10. 加载 bean 定义
    * 发布 application prepared 事件4️
11. refresh 容器
    * 发布 application started 事件5️
12. 执行 runner
    * 发布 application ready 事件6️

    * 这其中有异常,发布 application failed 事件7️