用源码方式打开SpringBoot的自动装配原理

用源码方式打开SpringBoot的自动装配原理

什么是装配?

学到SpringBoot的时候,有很多时候都忘记了在Spring会做的一件繁琐的事情,那就是把Bean对象托管到Spring Ioc容器,这个过程叫做装配,装配要写大量的xml文件,所以Spring被称为 配置地狱 。随后SpringBoot就是天降猛男,又来拯救程序员了,自动装配就是SpringBoot的核心之一


那么它怎么自动的?

又到了最激动人心的源码环节了,首先来看看主启动类(xxxApplication)。
在这里插入图片描述

可以看到 @SpringBootApplication 这个注解,外表看不出有什么,一个自定义的注解,继续深入。


在这里插入图片描述

前面四个注解都是java原生注解,感兴趣可以去了解,不是自动装配的核心。

  • @SpringBootConfiguration :这个注解是JavaConfig,其实就是一个IoC容器的配置类,这点也不是凭空捏造的,点进这个注解就会发现其有 @Configuration ,标注了@Configuration的Java类定义都是一个JavaConfig配置类。而在这个配置类中,任何标注了@Bean的方法,它的返回值都会作为Bean定义注册到Spring的IOC容器,方法名默认成为这个bean的id。

在这里插入图片描述


  • @EnableAutoConfiguration :这个注解才是自动装配的核心@Enable*开头的,一般都表示开启某项功能。

在这里插入图片描述

撕开发现也仅仅只有两个注解 @AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)

@AutoConfigurationPackage :也不是自动装配的核心,值得注意的是在SpringBootApplication注解上有 @ComponentScan 的注解,即扫描指定包下的组件,这里不绕弯子了,这个就是扫描与主启动类同级目录下的所有包,扫完后 @AutoConfigurationPackage 来注册。


那么说说最核心的地方 @Import(AutoConfigurationImportSelector.class)

@Import的作用

先了解以下@Import,在Spring的时候,还记得用处是把分开的IOC容器合并在一起,那么@Import也简单明了,就是一起加载被合并的容器。


那么深入 AutoConfigurationImportSelector 这个配置类

在这里插入图片描述

先要明确一点,那么就是AutoConfigurationImportSelector继承了ImportSelector接口,ImportSelector接口只有ImportSelector方法,该方法返回一个数组这个实例,在配置类中,返回值都会被Spring IOC容器托管。所有看看这个方法返回的是什么,到底装着什么东西。

在这里插入图片描述

该接口文档上说的明明白白,其主要作用是收集需要导入的配置类,selectImports()方法的返回值就是我们向Spring容器中导入的类的全类名

在这里插入图片描述

毫无疑问,要想知道返回值,那么就跟着它走,进入 getAutoConfigurationEntry() 方法,该方法返回是要导入的类的条目。

在这里插入图片描述

冷静分析,我们只关注返回值,返回的是什么,显而易见return new AutoConfigurationEntry(configurations, exclusions);exclusons是排除,所以不加理睬,关注configurations即可,可以看出List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);这里有我们想要的configurations,但是调用了getCandidateConfigurations()方法,继续跟进去。

在这里插入图片描述

跟到此处差不多快结束了,我们依旧关注返回值return configurations;,然后就可以知道返回值在哪定义的

List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
      getBeanClassLoader());

那么继续跟进到 SpringFactoriesLoader.loadFactoryNames() 方法中。

在这里插入图片描述

到这里,已经是真相大白了,loadFactoryNames()方法调用了下面的loadSpringFactories(),我们依旧关注返回值,result,我们就不多读源码了,我们正中靶心,找到加载了什么资源,放到了返回值中。

classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));

由此可得,是从这常量中获取到的资源,点进常量

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

发现其指定了一个地址,顺藤摸瓜

在这里插入图片描述

最终在该处找到了此资源,打开资源

在这里插入图片描述

全是我们需要装配的配置类,原来就是从自处读取来自动装配的。


总结

SpringBoot所有的自动配置都在启动时扫描加载,所有自动配置类都在META-INF/spring.factories中,但是却不一定生效,因为有的需要导入了相应的启动器依赖,才会生效,则点SpringBoot会有判断条件,这样做的目的是有效的减少@configuration类的数量从而降低SpringBoot的启动时间!所以只有导入相应的start启动器,自动装配才会生效,自动装配该启动器需要的配置类,会将所有导入的组件,以类名的方式返回,组件就会被添加到容器中。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thomasdududu~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值