目录
SpringBoot自动配置
SpringBoot自动配置-AutoConfiguration
-
指基于引入的jar包 对SpringBoot应用进行自动配置
(自动进行Bean的配置 省去了使用Spring框架时在xml中配置Bean这一步) -
为SpringBoot框架的开箱即用提供了基础支撑
配置类-ConfigurationClass
-
广义的: 被注解@Component直接或间接修饰的某个类 即我们常说的Spring组件
被@Component修饰的类本身作为Bean
-
狭义的: 被注解@Configuration所修饰的某个类 又称@Configuration类
被@Configuration修饰的类本身和其中被@Bean修饰的方法的返回值作为Bean
SpringBoot自动配置的例子
如自动配置redis
-
引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
-
配置redis服务器
spring: redis: database: 0 host: 127.0.0.1 port: 6379 password: 123456
-
直接使用RedisTemplate
@Autowired private RedisTemplate redisTemplate;
整个过程中 我们没有通过任何操作在applicationContext中注册RedisTemplate 这个Bean
SpringBoot启动流程
从SpringApplication.run(…)开始:
-
创建一个ApplicationContext实例 即创建ioc容器
-
注册主类到ioc容器中(简单但重要的一步)
被@SpringBootApplication所修饰的类
一般为main方法所在的类
这个类将作为遍历配置类的起点 -
递归加载并处理所有的配置类
SpringBoot自动找到所有的配置类
然后加载和处理他们 -
实例化所有的单例Bean
实例化所有的单例Bean
依赖注入和自动装配就属于其中的环节 -
如果是web应用 启动一个web服务器
步骤3-加载并处理所有的配置类
-
SpringBoot首先处理朱磊的@ComponentScan注解
扫描指定的package 得到一系列的配置类
包括@Component修饰的 @Configuration修饰的类
如果在这些扫描得到的配置类上存在@ComponentScan 则递归处理
以此步骤加载所有的程序中定义的配置类
-
处理注解@Import
根据Import注解的处理结果 可以得到一系列被导入的配置类
如果此步骤中得到的配置类上依然存在@Import注解 也是通过递归处理的
-
处理被@Bean修饰的方法
-
处理@Import导入的ImportBeanDefinitionRegistrar
-
加入到一个全局的配置类集合中
通过递归遍历 SpringBoot发现了所有的配置类
对配置类进行解析处理 并将得到的BeanDefinition注册到ioc容器中
@ComponentScan注解
-
对指定的package进行扫描 找到其中符合条件的类
-
默认是搜索被注解@Component修饰的配置类 (包括直接修饰的和间接修饰的)
-
通过属性basePackages或basePackageClasses来指定要进行扫描的package
-
如果未指定package 则默认扫描当前@ComponentScan所修饰的类所在的package
@Import注解
-
提供了一种显示的 从其他地方加载配置类的方式 用于避免使用性能较差的组件扫描(Component Scan)
-
支持导入:
-
普通类(非后面所说两个接口的实现类)
-
接口importSelector的实现类
-
接口importBeanDefinitionRegistrar的实现类
-
import导入普通类例子
导入ImportSelector接口的实现类例子
可以通过@import导入一个ImportSelector实现类
ImportSelector接口中的selectImports方法
他的返回值是一个字符串数组
数组中的每一个元素都代表一个将被导入的配置类的全限定名
利用这一特性 我们可以给ioc容器动态的导入多个配置类
导入接口ImportBeanDefinitionRegistrar实现类例子
在ImportBeanDefinitionRegistrar的实现类中
可以手动向registry(可以理解为目标ioc容器)中注册多个Bean定义
从而实现个性化定制
小结-SpringBoot加载配置类的方式
-
使用注解@ComponentScan
-
使用注解@Import
-
导入普通类
-
导入选择器ImportSelector
-
导入注册器 ImportBeanDefinitionRegistrar
-
实现自动配置的方式
如果@ComponentScan实现
通过包扫描向ioc容器中注册第三方jar包中定义的Bean
需要记住每个第三方jar包中需要被扫描的包的名称
然后在程序中进行扫描包
性能较差 使用不便 不符合SpringBoot开箱即用的理念
如果使用@Import导入普通类实现
需要记住具体的类名
虽然性能相比包扫描ComponentScan好
但依然使用不便
如果使用@Import导入注册器ImportBeanDefinitionRegistrar实现
ImportBeanDefinitionRegistrar导入的不是Bean
而是BeanDefinition
是针对@Bean方法的补充
用于实现自动配置并不恰当
(不理解…)
如果使用@Import导入选择器ImportSelector
SpringBoot实现自动配置使用的方式
@SpringBootApplicaton被@EnableAutoConfiguration注解修饰
@EnableAutoConfiguration注解被@Import(AutoConfigurationImportSelector.class)修饰
SpringBoot通过@Import(AutoConfigurationImportSelector.class)来实现自动配置
@SpringBootApplication注解结构
-
@SpringBootApplication修饰的类 会被@Configuration间接修饰 即"源配置类"
-
SpringBoot框架会对"源配置类"所在的package进行组件扫描(ComponentScan)
-
SpringBoot通过@Import(AutoConfigurationImportSelector.class)来实现自动配置
SpringBoot自动装配的原理
如何实现AutoConfigurationImportSelector
"开箱即用"即用户只需要引入jar包即可
不需要关心jar包中有哪些自动装配类
类名是什么 所在的包名是什么 都不需要用户关心
SpringBoot采用SpringFactories机制实现这一点
-
javaSPI机制的延申和扩展
-
SpringFactories是javaSPI设计思想的延申和扩展
-
SpringBoot基于它来实现的自动配置功能
SpringFactories机制
核心逻辑为:
从classpath中读取到所有jar包中的配置文件META-IF/spring.factories
然后根据指定的key从配置文件中解析出对应的value
AutoConfigurationImportSelector
在AutoConfigurationImportSelector的selectImports方法中:
-
通过SpringFactories机制加载配置文件
通过ClassLoader去获取classpath中的配置文件META-INF/spring.factories
-
找出所有的自动配置类
在所有的配置文件META-INF/spring.factories中
筛选出以EnableAutoConfiguration.class为key的 符合条件的配置类
(spring.factories内容格式为:“key=value1,value2,…valueN”) -
根据@Conditional过滤掉不必要的自动装配类
@Conditional 提供了配置过滤机制
在特定条件满足时才会向ioc容器注册指定组件
可以理解为一种特殊的if语句(待补充)
SpringFactories机制对比JavaSPI机制
-
相同的:
-
都要求第三方jar包提供配置文件
-
都使用ClassLoader.getResource(…)读取配置文件
-
-
不同的
-
约定的配置文件路径不同
-
SpringFactories机制:
META-IF/spring.factories -
JavaSPI机制:
META-IF/services/<Service接口的全限定名>
-
-
配置文件内容不同
-
SpringFactories机制:
内容格式为:“key=value1,value2,…valueN” -
JavaSPI机制:
内容格式是serviceProvider的类全限定名
多个Provider类的话每个类名占据一行
-
-
loader类不同
-
SpringFactories机制:
通过类SpringFactoriesLoader返回一个类名的集合
可以根据需求对这些类名进行下一步处理 -
JavaSPI机制:
返回一个ServiceProvider的对象实例集合
-
-
示意图
总结
SpringBoot实现bean自动配置
需要获知 在第三方jar包中 那些类是需要被配置的bean
只要能够获知这一点 就可以与配置程序中自定义bean相同的方式来处理这些类
获知这一点是使用了一种类似JavaSPI机制的方式:SpringFactories机制
SpringBoot在启动时 读取classpath下的所有spring.factories文件
从key为EnableAutoConfiguration.class的value中获取到所有需要进行自动配置的类的全限定名
至此 springBoot获取了实现自动配置需要的所有信息
此文章为https://www.bilibili.com/video/BV1NY411P7VX/?spm_id_from=333.788&vd_source=e974e5b422b5e93d638b7ac74272a918视频的学习笔记
感谢原内容作者码场安员外