- 入口:当@ConditionalOnXXX作用于带有@Configuration的类或带有@Bean的方法时,解析入口为ConfigurationClassParser.processConfigurationClass(ConfigurationClass)方法
1 | protected void processConfigurationClass(ConfigurationClass configClass) throws IOException { |
- 深入分析
conditionEvaluator.shouldSkip()作为condition判断的总入口,此方法传入Metadata和ConfigurationPhase,方法代码只列出关键逻辑
1 | public boolean shouldSkip(AnnotatedTypeMetadata metadata, ConfigurationPhase phase) { |
每个@ConditionalOnXXX的匹配结果通过Condition.matches()方法得出结果,具体的匹配逻辑就在这个方法里。可以看出:只要有一个Condition不匹配,方法直接返回true。这里的Condition实际上是SpringbootCondition,而SpringbootCondition是OnXXXCondition的父类,这是一个模板方法模式。注意一点:@ConditionalOnXXX对应OnXXXCondition类,方法内部如下
1 | public final boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata) { |
到这里都是通用的匹配逻辑,具体的OnXXXCondition自己的属性,字段匹配都有自己的getMatchOutcome()方法负责,这里以@ConditionalOnProperty(prefix = “spring.aop”, name = “auto”, havingValue = “true”, matchIfMissing = true)为例说下OnPropertyCondition.getMatchOutcome()的逻辑,如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
List<AnnotationAttributes> allAnnotationAttributes = annotationAttributesFromMultiValueMap(
metadata.getAllAnnotationAttributes(ConditionalOnProperty.class.getName()));
for (AnnotationAttributes annotationAttributes : allAnnotationAttributes) {
ConditionOutcome outcome = determineOutcome(annotationAttributes,context.getEnvironment());
(outcome.isMatch() ? match : noMatch).add(outcome.getConditionMessage());
}
if (!noMatch.isEmpty()) {
return ConditionOutcome.noMatch(ConditionMessage.of(noMatch));
}
return ConditionOutcome.match(ConditionMessage.of(match));
}
private ConditionOutcome determineOutcome(AnnotationAttributes annotationAttributes,
PropertyResolver resolver) {
Spec spec = new Spec(annotationAttributes);
spec.collectProperties(resolver, missingProperties, nonMatchingProperties);
}
private void collectProperties(PropertyResolver resolver, List<String> missing,List<String> nonMatching) {
if (this.relaxedNames) {
resolver = new RelaxedPropertyResolver(resolver, this.prefix);
}
for (String name : this.names) {
String key = (this.relaxedNames ? name : this.prefix + name);
if (resolver.containsProperty(key)) {
if (!isMatch(resolver.getProperty(key), this.havingValue)) {
nonMatching.add(name);
}
}
else {
if (!this.matchIfMissing) {
missing.add(name);
}
}
}
}
resolver是用来解析Environment中配置文件的,所以collectProperties()方法的逻辑为:如果resolver在配置文件中找到了spring.aop.auto这个key且spring.aop.auto=havingValue则匹配成功,或者配置文件中没有spring.aop.auto这个key且matchIfMissing为true则匹配成功,其他任何逻辑都是匹配失败。
- 看到这里,是不是对我们总迷惑的havingValue和matchIfMissing的含义彻底的明白了。所以,走源码可以为你解惑