一.@Conditional条件注解概述

1.作用于方法和类上面,value是实现Condition接口类型,一个判断是否匹配的方法,返回true/false,例如

如果是Windows系统,且@Conditional注解宿主上有@Controller注解时,返回true,对应controller类要加载进容器中实例化,否则false不加载

2.ConditionContext类封装了spring容器的配置和环境信息,通过这个对象可以关联到容器的所有内容,为实现无限扩展提供可能

3.AnnotatedTypeMetadata类,可以简单理解成注解的宿主(因为注解不可能单独存在,必须要有对应宿主),像类、方法、属性等,当然在这里只可能是类和方法

二.原理

1.简单来说,容器启动好刷新的时候,有一个扫描器,对路径下class类进行扫描,如果类上有@Conditional注解,调用其value值对应的接口方法,返回true/false,判断是否将该class加载进容器

2.调用时机是ConfigurationClassPostProcessor BeanFactory后置处理器接口的postProcessBeanDefinitionRegistry方法

3.解析类对象ConfigurationClassParser(构造方法中创建ComponentScanAnnotationParser和ConditionEvaluator),ComponentScanAnnotationParser对象负责扫描class信息,ConditionEvaluator对象负责校验

4.ConditionEvaluator对象封装了spring容器的信息,shouldSkip方法负责注解校验

1).有没有@Conditional注解,没有直接结束true

2).有@Conditional注解,取到注解里value的值,可能有多个@Conditional注解

3).根据value值反射出对应的Condition接口实例对象,多个的话放到集合中,排序

4).循环执行接口方法matches,校验是否匹配

5.条件满足的话,class被解析成ConfigurationClass对象,然后封装成BeanDefinition对象,最后实例化成spring容器中的bean对象

三.springboot中,对@Conditional注解进行扩展

1.@ConditionalOnClass:OnClassCondition(Condition接口实现类)取到spring容器中的类加载器classLoader,加载注解value对应的class,判断是否加载到

2.@ConditionalOnBean:OnBeanCondition(Condition接口实现类)取到spring容器,注解value对应的class名称,判断容器中有没有对应的bean对象

3.@ConditionalOnResource、@ConditionalOnProperty等等,原理都一样

4.FilteringSpringBootCondition、SpringBootCondition是两个抽象模版类,抽取出来公共的逻辑;ConditionOutcome类对匹配结果的封装

四.正是借助于@Conditional注解的扩展,springboot才能实现自动装配,内置很多默认配置进autoconfigure系统,根据条件选择加载进spring容器中