上篇文章讲了ConfigurationClassPostPreocessor类生成BeanDefinition的时机、以及概括了它做的事,它是整个注解开发的支撑,今天来具体细品。

1.看ConfigurationClassPostPreocessor类的postProcessorBeanDefinitionRegistry()方法

14.spring源码之@Conditional注解_属性文件

2.进入processConfigBeanDefinitions()方法

14.spring源码之@Conditional注解_封装_02

2.1进入checkConfigurationClassCandidate()方法

这个方法就是获取BeanDefinition的metadata,从metadata中获取注解信息判断是full匹配还是lite匹配,如果都不是,说明这个BeanDefinition不需要处理。返回false。

14.spring源码之@Conditional注解_自定义注解_03

14.spring源码之@Conditional注解_属性文件_04

进入isConfigurationCandidate()方法,这个方法就是收集哪些注解是lite匹配。

14.spring源码之@Conditional注解_自定义注解_05

candidateIndicators容器如下:

14.spring源码之@Conditional注解_实例化_06

endi.........

接着processConfigBeanDefinitions()方法继续往下看

14.spring源码之@Conditional注解_属性文件_07

14.spring源码之@Conditional注解_自定义_08

14.spring源码之@Conditional注解_封装_09

14.spring源码之@Conditional注解_属性文件_10

2.2进入parse()方法

14.spring源码之@Conditional注解_封装_11

在进入parse()方法,注意把metadata和beanName封装成了一个ConfigurationClass,然后把ConfigurationClass作为参数传进去了

14.spring源码之@Conditional注解_属性文件_12

进入processConfigurationClass()方法如下,如果shouldSkip()方法返回true,那么流畅就结束了,不需要处理。

14.spring源码之@Conditional注解_实例化_13

进入shouldSkip()方法

14.spring源码之@Conditional注解_实例化_14

3.根据这个代码就知道@Conditional注解该怎么应用

@Conditional注解的value是一个Condition类型的Class对象或数组

14.spring源码之@Conditional注解_属性文件_15

自定义一个注解,使用@Conditional注解,如下:

14.spring源码之@Conditional注解_属性文件_16

可以知道OnPropertyCondition必须是一个Condition类型的,创建OnPropertyCondition类实现Condition接口,如下:

14.spring源码之@Conditional注解_实例化_17

Condition接口有一个返回boolean类型的match()方法,根据上面源码中的shouldSkip()源码知道,如果match()返回false那么流程就结束了,那么就没有生成BeanDefinition,就无法实例化,创建一个类使用自定义注解

14.spring源码之@Conditional注解_实例化_18

ConditionBean类上加了我们自定义的注解,而我们的自定义注解使用了一个@Conditional注解,在match方法中进行了一些逻辑处理,去获取属性文件以ConditionOnProperty的name为key的值是否为true,如果为true,则match方法返回true,否则返回false,如果属性文件中cn.enjoy.flag为false,那么ConditionBean是无法实例化的。

14.spring源码之@Conditional注解_封装_19

测试:

14.spring源码之@Conditional注解_自定义注解_20

把属性文件中cn.enjoy.flag改为true

14.spring源码之@Conditional注解_自定义_21

在测试

14.spring源码之@Conditional注解_实例化_22

获取到了实例。