SpringBoot条件注解底层原理

一、简介

相信大家在学springBoot自动装配的时候会遇到下面这些条件注解,当存在其指定的条件,才会把对应的bean注入到IOC容器中。本博客旨在揭开其神秘的面纱!
SpringBoot条件注解底层原理_第1张图片
其实说白了,springBoot的这些注解只是针对普通spring框架中@Condition注解的扩展,使其功能更加强大罢了!下面我们以分析@ConditionalOnClass为例子,简单介绍一下它的实现原理。

二、源码分析

2.1@ConditionalOnClass的上方标注了@Condition注解,我们只需要看其配置的条件类即可!

SpringBoot条件注解底层原理_第2张图片

2.2通过uml类图可以看到其继承了Condition接口

SpringBoot条件注解底层原理_第3张图片
在父类的SpringBootCondition中实现了核心的matches方法,其中圈出来的部分是个抽象方法,需要子类自己单独实现,这样我们接着看OnClassCondition#getMatchOutcome就行了!
SpringBoot条件注解底层原理_第4张图片

2.3接着分析getMatchOutcome

首先我们可以看到OnClassCondition的这个方法的getMatchOutcome,会处理@ConditionalOnClass、@ConditionalOnMissingClass这两个注解!我们看第一个大if代码块就行!
图中的圈出来的代码就很有意思,底层通过classloader尝试去加载注解配置的类,如果加载异常就说明这个类不存在,于是就放进onMissingClasses中!
后续逻辑也很清晰明了,有缺损的class那么自然不符合注入条件,那么会返回match=false的ConditionOutcome!

SpringBoot条件注解底层原理_第5张图片

2.4回到父类SpringBootCondition中的matches方法

很显然如果第三步存在缺损的class(onMissingClasses列表不为空),那么就会返回false,告诉spring容器不要注入这个bean
SpringBoot条件注解底层原理_第6张图片

三、普通的Spring怎么处理Condition注解的

二中我们只分析到了SpringBoot中的源码,看到matches方法返回为false,至于为什么这个方法返回为false就不注入这个bean的逻辑还的看普通的spring源码,咱们怀着探索精神也去了解一下:

3.1Spring在启动的时候会自带一个叫ConfigurationClassPostProcessor的BeanFactory后置处理器

具体调用的时机是在refresh方法中的invokeBeanFactoryPostProcessors,具体源码我就不带大家追了,直接看ConfigurationClassPostProcessor#processConfigBeanDefinitions这个方法吧,再这个方法中我们也只需要关心他是怎么处理配置类的,也就是我圈出来的部分!
SpringBoot条件注解底层原理_第7张图片

3.2上图圈出来的部分最后会调用到ConfigurationClassParser#processConfigurationClass

其方法的第一行就是处理@Condition注解的逻辑
SpringBoot条件注解底层原理_第8张图片

3.3接着我们直接看shouldSkip方法

如果shouldSkip返回为true那么就不放进configurationClasses这个map中后续也不会加载其BeanDefinition,也就不会把这个Bean放入IOC容器中!可以在shouldSkip中看到调用了Condition的matches方法。matches方法返回为false也就是不满足Condition的条件,shouldSkip才会返回true!
SpringBoot条件注解底层原理_第9张图片

四、其他条件注解的简单介绍

  • 4.1@ConditionalOnBean:底层会通过BeanFactory来尝试获取条件bean是否存在
  • 4.2@ConditionalOnProperty:底层会通过Environment获取properties文件中配置的属性的值
  • 4.3@ConditionOnJava:这个注解是用java版本来当充当判断条件的,里面比较有意思的是如何获取当前项目的java版本(JavaVersion#getJavaVersion),针对老版本的springboot是通过是否存在某个类来判断的,新版本的springboot是通过存在某个类和类方法来进行判断的
  • 4.4@ConditionalOnWebApplication:底层是通过是否存在GenericWebApplicationContext这个类以及其作用域有session这个作用域等其他条件来判断出是servlet应用,如果有reactive.HandlerResult这个类加上其他条件来判断是否是Reactive的web应用。

你可能感兴趣的:(springboot,spring,boot,后端,java)