目录

1、自动配置读取原理源码解析

(1)@SpringBootConfiguration 

(2)@ComponentScan

(3)@EnableAutoConfiguration

2、Springboot 自动配置类的使用


Spring Boot 自动配置流程图示

本地配置spring配置中心_自动配置原理

1、自动配置读取原理源码解析

从 @SpringBootApplication

@SpringBootApplication 注解由以下注解组成

本地配置spring配置中心_本地配置spring配置中心_02

关于Java元注解,可以查看这篇文章《Java注解解析和使用

(1)@SpringBootConfiguration

@SpringBootConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration // 标记为配置类
public @interface SpringBootConfiguration {
}

(2)@ComponentScan

@ComponentScan 包扫描注解,相当于 spring.xml 配置中的 <context:component-scan base-package="com.xxx.xxx" />,如果没有指定 basepackage,会自动扫描当前注解配置类所在的包和所在包下的所有子包。// 所以被@SpringBootApplication 标注的类总是放置在项目的最外层包

(3)@EnableAutoConfiguration

@EnableAutoConfiguration

本地配置spring配置中心_本地配置spring配置中心_03

@AutoConfigurationPackage 注解,负责保存标注相关注解的类的所在包路径。使用一个BasePackage类,保存这个路径。然后使用 @Import 注解将其注入到 ioc 容器中。随后,Spring 可以在容器中拿到该路径。

本地配置spring配置中心_SpringBoot自动配置_04

@Import 注解只能用在类上 ,通过快速导入的方式实现把实例加入 spring 的 IOC 容器中

SpringBoot 通过 @Import  注解导入了一个 AutoConfigurationImportSelector.class 的类

@Import(AutoConfigurationImportSelector.class)

AutoConfigurationImportSelector.class 实现了 DeferredImportSelector 接口(DeferredImportSelector 是 ImportSelector 的一种), 在 ImportSelector

本地配置spring配置中心_SpringBoot自动配置_05

DeferredImportSelector#selectImports() 方法的执行逻辑:如果实现类实现了 getImportGroup() 方法(返回值不为空且实现了DeferredImportSelector.Group),那么就调用 Group 类中的selectImports() 方法,否则调用实现类的 selectImports() 方法。

本地配置spring配置中心_spring boot_06

SpringBoot 中 AutoConfigurationImportSelector 实现了 getImportGroup() 方法,返回了一个AutoConfigurationGroup.class

本地配置spring配置中心_自动配置源码_07

在 AutoConfigurationGroup.class 中,会先调用 process() 方法获取自动配置类,然后调用 selectImports() 方法把获取到的自动配置类封装成 Iterable<Entry> 返回

在 AutoConfigurationGroup#process 中,process#getAutoConfigurationEntry会获取到所有的自动配置类

本地配置spring配置中心_自动配置源码_08

process#getAutoConfigurationEntry 中会获取所有的候选配置,然后通过一系列筛选才返回最终的自动配置类

本地配置spring配置中心_本地配置spring配置中心_09

getAutoConfigurationEntry#getCandidateConfigurations 真正的去获取配置类,那么它是怎么获取这些配置文件的呢?

使用 getCandidateConfigurations#loadFactoryNames 加载配置文件

本地配置spring配置中心_spring boot_10

loadFactoryNames 中的详细执行逻辑如下,它会去加载 META-INF/spring.factories

本地配置spring配置中心_自动配置原理_11

至此,SpringBoot 自动配置的读取流程就已经完成了。

附:

每一个 SpringBoot 应用,都会引入 spring-boot-autoconfigure.jar ,jar包中 META-INF/ 目录下包含一个 spring.factories

本地配置spring配置中心_自动配置源码_12

为什么会是 org.springframework.boot.autoconfigure.EnableAutoConfiguration ?

还记得使用 getCandidateConfigurations#loadFactoryNames 加载配置文件这个方法吗?

本地配置spring配置中心_spring boot_10

其中有一个参数是通过 getSpringFactoriesLoaderFactoryClass() 获取的,这个方法的会返回一个EnableAutoConfiguration

本地配置spring配置中心_spring boot_14

这个 EnableAutoConfiguration 就是 org.springframework.boot.autoconfigure.EnableAutoConfiguration

本地配置spring配置中心_自动配置原理_15

然后 loadFactoryNames 会根据这个 EnableAutoConfiguration 的名字做为筛选条件,把所有的 xxxAutoConfiguration 封装成一个 List<String> 集合

本地配置spring配置中心_自动配置源码_16

每一个这样的 xxxAutoConfiguration 类都是容器中的一个组件,xxxAutoConfiguration 类中的Bean 会加入到 IOC 容器中,从而实现自动配置。

注:@EnableAutoConfiguration 注解,通过 @SpringBootApplication 被间接的标记在了 SpringBoot 的启动类上。在 SpringApplication.run(...) 内部就会执行 selectImports() 方法,从而找到所有JavaConfig 自动配置类的全限定名对应的class,然后将所有自动配置类加载到 Spring 容器中。

2、Springboot 自动配置类的使用

以 HttpEncodingAutoConfiguration 自动配置文件为例

在 spring-boot-autoconfigure.jar 的 spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=
// 省略...
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
// 省略...

HttpEncodingAutoConfiguration.class 文件的内容如下

本地配置spring配置中心_本地配置spring配置中心_17

其中  HttpProperties.class 里边的属性就是我们通过 application.properties

@ConfigurationProperties(prefix = "spring.http") // 绑定外部配置文件的命名属性

本地配置spring配置中心_SpringBoot自动配置_18

假如,我们在 application.properties 中配置如下属性

本地配置spring配置中心_SpringBoot自动配置_19

那么 SpringBoot 启动时,会自动加载到这个属性的值 

本地配置spring配置中心_spring boot_20

至此,完成一个自动配置的属性注入。