Spring Boot的自动装配原理(易懂)
熟练使用Spring Boot那么自动装配原理的掌握是必不可少的
文章目录
- Spring Boot的自动装配原理(易懂)
- 一、自动装配是什么
- 二、启动类注解流程关系分析
- 1.首先展示`@SpringBootConfiguration`注解流程图
- 2.代码块展示`@SpringBootConfiguration`注解流程
- 3.注解含义
- 三、详细介绍
- 1.`@AutoConfigurationPackage`默认包规则详解
- 2.`@Import(AutoConfigurationImportSelector.class)`进行自动配置详解
- 3.当前接口为上图3位置的批量导入器接口
- 4.当前方法为上图4位置的运行结果
- 四、分析条件装配原理
- 1.谈到Spring Boot项目最重要的`starter`场景启动器
- 2.最重要的控制器(dispatcherServlet)
- 3.文件上传解析器配置
- 4.字符集配置
- 五、总结
- 1.为什么不一次全部加载到容器中
- 2.简单总结:
- 3.详细总结
一、自动装配是什么
Spring Boot的自动装配实际上是从
META-INF/spring.factories
文件中获取到对应的需要进行自动装配的类,并生成相应的Bean对象,然后将它们交给Spring容器进行管理
二、启动类注解流程关系分析
@SpringBootApplication
public class EntryApplication {
public static void main(String[] args) {
SpringApplication.run(EntryApplication.class, args);
}
}
1.首先展示@SpringBootConfiguration
注解流程图
2.代码块展示@SpringBootConfiguration
注解流程
启动类的@SpringBootAppliation注解是一个组合注解,由以下3个注解组成
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
其中@EnableAutoConfiguration 注解又分为以下两种注解
@AutoConfigurationPackage
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件
public @interface AutoConfigurationPackage {}
//利用Registrar给容器中导入一系列组件
其中@AutoConfigurationPackage 注解则由以下注解构成
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
3.注解含义
@SpringBootConfiguration
: 标注在某个类上,表示这是一个Spring Boot的配置类;
@ComponentScan
: 配置扫描路径,用于加载使用注解格式定义的bean
@EnableAutoConfiguration
: 开启自动装配功能
@AutoConfigurationPackage
就是将主程序类所在包及所有子包下的组件扫描到Spring容器中;
@Import(AutoConfigurationImportSelector.class)
: 通过@Import
注解导入AutoConfigurationImportSelector
类,然后通过该类的 方法去读取MATE-INF/spring.factories
文件中配置的组件的全类名,并按照一定的规则过滤掉不符合要求的组件的全类名,将剩余读取到的各个组件的全类名集合返回给IOC容器并将这些组件注册为bean
三、详细介绍
1.@AutoConfigurationPackage
默认包规则详解
2.@Import(AutoConfigurationImportSelector.class)
进行自动配置详解
1、利用
getAutoConfigurationEntry
(annotationMetadata);给容器中批量导入一些组件
2、调用List configurations =getCandidateConfigurations
(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
3、利用工厂加载 Map<String, List>loadSpringFactories
(@Nullable ClassLoader classLoader);得到所有的组件
4、从META-INF/spring.factories
位置来加载一个文件。默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件**,
3.当前接口为上图3位置的批量导入器接口
4.当前方法为上图4位置的运行结果
四、分析条件装配原理
@Conditional
1.谈到Spring Boot项目最重要的starter
场景启动器
Spring Boot所有的自动配置功能都在 spring-boot-autoconfigure
包里面,Spring Boot 自动装配会通过引入了哪些场景这个场景的自动配置才会开启生效,
2.最重要的控制器(dispatcherServlet)
Spring MVC中最重要的控制器(dispatcherServlet
)也配置好了
3.文件上传解析器配置
@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {
//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}
给容器中加入了文件上传解析器;
以前Spring MVC中要配置文件解析器,名字必须叫multipartResolver
,但是很多人不知道默认行为,Spring Boot可以将你配置的解析器,用默认名称返回,防止不符合规范
4.字符集配置
五、总结
最重要的包
spring-boot-autoconfigure
Spring Boot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先
1.为什么不一次全部加载到容器中
如果Spring没有添加任何的附加条件,此时这些配置类中所定义的bean都会被导入到Spring容器中,这样
非常消耗内存
,因此在Spring中提供了很多的条件注解,通过这些条件注解控制某一个配置是否生效。
2.简单总结:
在项目启动的时候,Spring Boot框架会自动读取
META-INF/spring.factories
配置文件中org.springframework.boot.autoconfigure.EnableAutoConfiguration
所配置的配置类,然后将其中所定义的bean根据条件注解所指定的条件来决定是否需要将其导入到Spring容器中。
3.详细总结
- 在Spring Boot项目中有一个注解
@SpringBootApplication
,这个注解是对三个注解进行了封装:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan
其中@EnableAutoConfiguration
是实现自动化配置的核心注解。 - 该注解通过
@Import
注解导入AutoConfigurationImportSelector,这个类实现了一个导入器接口ImportSelector
。在该接口中存在一个方法selectImports, - 该方法的返回值是一个数组,数组中存储的就是要被导入到spring容器中的类的全类名。在AutoConfigurationImportSelector类中重写了这个方法,
- 该方法内部就是读取了项目的classpath路径下
META-INF/spring.factories
文件中的所配置的类的全类名。 - 在这些配置类中所定义的Bean会根据条件注解所指定的
条件
来决定是否需要将其导入到Spring容器中。
文章出处登录后可见!