SpringBoot自动装配流程
准备工作
1 |
|
拆分@SpringBootApplication注解
1 | # 标注该类是主启动类 |
接下来重点关注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 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ |
Spring能确认自己写的不会重复,但是它不能保证你不加个重复的啊
getExclusions
checkExcludedClasses
检查排除的类是否在org.springframework.boot.autoconfigure.EnableAutoConfiguration
配置中
如果不存在则不允许排除,抛出异常
configurations.removeAll(exclusions);
即将configurations排除exclusions
getConfigurationClassFilter().filter(configurations);
在过滤后,configurations就只剩下可怜的13个了
fireAutoConfigurationImportEvents
这个不太确定
最后就将其封装成AutoConfigurationEntry
对象返回