SpringBoot自动装配底层原理和源码追踪

众所周知,SpringBoot的自动装配是其一大特色,也是我们使用的最多的部分,那么他的底层是如何实现的呢?今天来探寻一下。

自动配置的作用 主要是启动类的@SpringBootApplication注解发挥作用

打开看@SpringBootApplication的源码看一下

除了元注解 里面还包括了@ComponentScan注解组件扫描

以及@SpringBootConfiguration 和@EnableAutoConfiguration

@SpringBootConfiguration 中除了三个元注解

就只剩一个@Configuration(用于标识是一个 配置类) 和 @Indexed(加速应用启动)

@EnableAutoConfiguration注解

可以发现 这就是上面 解决方案2 中提到的 @Enablexxxx系列的注解

一般该类注解内部都封装了 @Import注解 事实上也的确

该注解中 @Import 了一个 Auto.....ImportSelector.class 即导入了一个普通类 并且是一个ImportSelector接口的实现类 结合之前的 解决方案2

我们可以知道 这个注解的作用应该就是 自动配置了

进入到该类 然后查看其实现的一个接口 DeferredImportSelector

发现该接口即 ImportSelector的子接口 直接查看 ImportSelector接口源码

因为 ImportSelector 接口中有个方法的返回值为String数组 该数组封装了要导入自动封装的类名 底层上即:

selectImports(AnnotationMetadata importingClassMetadata);

找到该方法的实现

发现该类的返回值即是将

autoConfigurationEntry.getConfigurations()

的返回值通过StringUtils转为了String数组

该 ... Entry对象 是通过上一行的 get...方法获取的 那么我们再次跟踪该方法到Entry对象的创建上 发现Entry对象的创建又和 configurations相关 configurations是一个List集合 再次进去看看该集合的内容

我们看到getCandidateCanfigurations方法

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = new ArrayList(SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()));
    ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).forEach(configurations::add);
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.");
    /*重点看上面红色的断言部分  即
    如果 configurations为空  则输出在METAINF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports.
META-INF/spring.factories 
两个文件中没有对应的自动配置类
    */
    return configurations;
}

在外部库中找到这两个文件并且查看

可以看到 我们找到的这两个对应的文件

里面全是一些类的全类名

所以Spring Boot的自动配置实质就是 将这些需要自动配置的类的全类名先保存在这些文件中 然后读取到List集合里面 然后通过@Import注解读取导入

@Conditional系列注解

我们稍微对比一下IOC容器里面的bean对象和储存全类名的文件就可以发现

其实并不是所有类都创建了对应bean对象存储到了IOC中 可以发现启动即创建bean对象的类都有个@Conditional....注解

@Conditional注解的作用:按照一定的条件进行判断 当条件满足后才会将该类注册对应的bean对象到IOC容器中 可以作用于方法/类 要配合@Bean或者@Component注解一起使用

他是一个父注解 衍生出很多子注解

@ConditionalOnClass

判断环境中是否有对应的字节码文件,才注册Bean对象到IOC容器

有两个属性:String[] name 属性值为 全类名

class<?>[] value 属性值为 字节码文件对象

把相关依赖注释掉后 运行测试方法 发现的确没有创建对应的bean对象

就是因为 jwt 的类不存在 所以不会去配置对应的bean对象

@ConditionalOnMissingBean:

判断环境中没有对应的bean对象的时候,才注册bean到 IOC中

这个注解的功能就很直白 默认情况下是判断本类(即被注解标记的类) 无则创建 但是该直接也可以 自己指定类型(value属性)/名称(name属性)来判断 即判断指定名称/类型的bean对象是否存在

@ConditionalOnProperty:

判断配置文件中对应的属性和值,才注册bean到IOC

该注解有两个重要的属性 name="A" havingValue="B"

即判断 配置文件中(yml ymal properties)是否存在属性A并且值为B

当没有/值不存在/属性不存在

当属性和值都存在

还有很多

综上,就是对SpringBoot自动装配的相关介绍,有其他想法的请私聊或者评论区交流

  • 24
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ZealSinger

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

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

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

打赏作者

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

抵扣说明:

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

余额充值