1.自动配置的原理
springBoot项目都会有一个启动类,启动类上有一个@SpringBootApplicaion注解,这个注解是一个组合注解,主要有三部分组成:
1、@SpringBootConfiguration
2、@EnableAutoConfiguration
3、@CompoentScan
其中,第一个注解表明了这个启动类是一个配置类,唯一特殊的是这个配置类有且只能有一个
第三个注解:扫描启动类所在的包以及子包下的所有标记为Bean或者派生注解的组件扫描并注册到IOC容器中
springBoot完成自动配置最关键的是依靠第二个注解@EnableAutoConfiguration
我们来看一下@EnableAutoConfiguration注解
这个注解也是一个注解.里面有两个主要注解:
1、@AutoConfigurationPackage
2、@Import(AutoConfigurationImportSelector.class):这个注解导入了AutoConfigurationImportSelector这个类,这个类会扫描类路径下的spring.factories文件。
AutoConfigurationImportSelector这个类会调用selectImports方法返回所有需要被注册为bean的类的全名的String[]数组集合,
**为什么不使用 @Import 直接引入自动配置类**
有两个原因:
1. 让主配置类和自动配置类变成了强耦合,主配置类不应该知道有哪些从属配置
2. 直接用 `@Import(自动配置类.class)`,引入的配置解析优先级较高,自动配置类的解析应该在主配置没提供时作为默认配置。
springBoot启动过程
我们可以看到启动类里面只有一个静态方法run
点进这个run方法
发现还是个run方法,我们再点进去
啊,可以发现分为了两个步骤,一个是新建一个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️