SpringBoot自动装配流程

SpringBoot自动装配流程

准备工作

1
2
3
4
5
6
@SpringBootApplication
public class SpringStartProcessApplication {
public static void main(String[] args) {
SpringApplication.run(SpringStartProcessApplication.class,args);
}
}

拆分@SpringBootApplication注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 标注该类是主启动类
@SpringBootApplication
@SpringBootConfiguration
# 配置类
@Configuration
# 加快SpringBoot启动
@Indexed
# 开启自动装配
@EnableAutoConfiguration
# 设置扫描包的路径
@AutoConfigurationPackage
# 导入一个类
@Import(AutoConfigurationPackages.Registrar.class)
# 加载META-INF/spring.factories,将beandefinitions装入容器
@Import(AutoConfigurationImportSelector.class)
# 用来排除一些自动配置类
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

接下来重点关注AutoConfigurationPackages.Registrar类和AutoConfigurationImportSelector

AutoConfigurationPackages.Registrar

先在AutoConfigurationPackages.Registrar的图示位置打上断点,接着启动程序

分析源码要由内而外的分析

方法参数中有一个new出来的对象,直接单步调试进去

1、metadata到底是哪个类的注解元信息?

其实是启动类的,也就是SpringStartProcessorApplication

2、这个basePackages和basePackageClasses在哪里体现的呢?

其实是在SpringBootApplication注解上

这也就说明这个metadata包括了@SpringBootApplication标注的类上的其他注解的元信息和自身内部的注解的元信息

ok这段代码解决,现在继续点进去,看这个register方法里面写了啥

AutoConfigurationImportSelector

既然知道了这个类的作用,所以找到selectImports方法,打上断点,启动程序等待程序停止

但是!你会发现断点并没有生效

实际上断点应该打在AutoConfigurationGroup类的process方法

点进getAutoConfigurationEntry方法

ps:这里的attributes是取出exclude和excludeName,就是用于排除掉不需要加载的自动配置类
这两个属性是在@SpringBootApplication中配的,是从@EnableConfiguration中得来的

getCandidateConfigurations

点进SpringFactoriesLoader.loadFactoryNames方法

点进loadSpringFactories方法

然后在这里就会发现这个result竟然不是null,直接返回了result

哎不是,我还没执行下面的逻辑呢,怎么就走缓存了

其实这步加载在刚开始的时候就做了,所以直接在下面打一个断点,然后重新执行

你会发现之前的那些断点都没有起作用,而是直接停在了这一行

现在找一下auto-configuration包下的META-INF/spring.factories文件

可以看到这些类都有一个统一的特征,那就是都是以AutoConfiguration结尾

随便点开一个看,发现都长得差不多

注意:这里会加载类路径下所有的META-INF/spring.factories文件

每一个url就是一个jar包下的META-INF/spring.factories文件

好,现在我们加载了所有jar包下的META-INF/spring.factories文件

现在放行,一直到这一步

为什么要框住131这个数字?

你现在回到刚刚那个spring.factories文件

数一下org.springframework.boot.autoconfigure.EnableAutoConfiguration后面有几个类的全限定名

对,正正好好131个

removeDuplicates

这个方法就是给list去重的,简单的赖,我来我也行!

为什么要做去重?这个文件不是spring自己写的吗?它自己还不敢确定这个类不会重复吗?

刚刚提到了,这里会加载所有类路径下的spring.factories文件,所以我如果这样呢
我在我自己的类路径下面创建一个spring.factories文件

内容如下

1
2
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration

Spring能确认自己写的不会重复,但是它不能保证你不加个重复的啊

getExclusions

checkExcludedClasses

检查排除的类是否在org.springframework.boot.autoconfigure.EnableAutoConfiguration配置中

如果不存在则不允许排除,抛出异常

configurations.removeAll(exclusions);

即将configurations排除exclusions

getConfigurationClassFilter().filter(configurations);

在过滤后,configurations就只剩下可怜的13个了

fireAutoConfigurationImportEvents

这个不太确定

最后就将其封装成AutoConfigurationEntry对象返回

给作者买杯咖啡吧~~~