关于spring:Spring-Boot自动装配原理易懂

5次阅读

共计 3832 个字符,预计需要花费 10 分钟才能阅读完成。

Spring Boot 的主动拆卸原理(易懂)

纯熟应用 Spring Boot 那么主动拆卸原理的把握是必不可少的


一、主动拆卸是什么

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 注解流程图

graph TD
A["@SpringBootApplication"]
A-->B["@SpringBootConfiguration"]
A-->C["@EnableAutoConfiguration"]
A-->D["@ComponentScan"]
C-->E["@AutoConfigurationPackage"]
C-->F["@Import(AutoConfigurationImportSelector.class)"]
E-->G["@Import(AutoConfigurationPackages.Registrar.class)"]

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 $\color{#F0F}{指定了默认的包规定}$ 就是将主程序类所在包及所有子包下的组件扫描到 Spring 容器中;
@Import(AutoConfigurationImportSelector.class) : 通过 @Import 注解导入 AutoConfigurationImportSelector类,而后通过该类的 $\color{#F0F}{selectImports}$ 办法去读取 MATE-INF/spring.factories 文件中配置的组件的全类名,并依照肯定的规定过滤掉不符合要求的组件的全类名,将残余读取到的各个组件的全类名汇合返回给 IOC 容器并将这些组件注册为 bean

三、具体介绍

1.@AutoConfigurationPackage默认包规定详解

2.@Import(AutoConfigurationImportSelector.class)进行主动配置详解

1、利用 getAutoConfigurationEntry(annotationMetadata); 给容器中批量导入一些组件
2、调用 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes) 获取到所有须要导入到容器中的配置类
3、利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);失去所有的组件
4、从META-INF/spring.factories 地位来加载一个文件。默认扫描咱们以后零碎外面所有 META-INF/spring.factories 地位的文件 **,$\color{#F0F}{依照条件拆卸(@Conditional)最终会按需配置}$

 


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. 具体总结

  1. 在 Spring Boot 我的项目中有一个注解 @SpringBootApplication,这个注解是对三个注解进行了封装:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan
    其中 @EnableAutoConfiguration 是实现自动化配置的外围注解。
  2. 该注解通过 @Import 注解导入 AutoConfigurationImportSelector,这个类实现了一个导入器接口ImportSelector。在该接口中存在一个办法 selectImports,
  3. 该办法的返回值是一个数组,数组中存储的就是要被导入到 spring 容器中的类的全类名。在 AutoConfigurationImportSelector 类中重写了这个办法,
  4. 该办法外部就是读取了我的项目的 classpath 门路下 META-INF/spring.factories 文件中的所配置的类的全类名。
  5. 在这些配置类中所定义的 Bean 会依据条件注解所指定的 条件 来决定是否须要将其导入到 Spring 容器中。
正文完
 0