条件注解:
ConditionalOnClass(***) 当***class存在时 被注解的类才实例化。
@Conditional({OnClassCondition.class}) @ConditionalOnClass { Class<?>[] value() {}String[] name() {}}
首先看一下注解Conditional
@Target({ElementType.TYPEElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional { Class<? Condition>[] value()}
他的值是一个Condition的实现类的数组。
当一个类被Condtional注解后,当它被注入spring容器之前会进行条件判断 AnnotatedBeanDefinitionReader.register->registerBean 最终调用到ConditionEvaluator.shouldSkip这个方法,这里就是根据条件要不要跳过注入的方法。这个方法会获取Condtional注解里的所有条件类,然后按顺序调用他们的matches方法
{ { (!var4.hasNext()) { } condition = (Condition)var4.next()requiredPhase = (condition ConfigurationCondition) { requiredPhase = ((ConfigurationCondition)condition).getConfigurationPhase()} } (requiredPhase != && requiredPhase != phase)} (condition.matches(.contextmetadata))
现在在回到ConditionalOnClass注解,可以看到这是个复合注解,他上面有Conditional注解,里面有个OnClassCondition.class,它是SpringBootCondition的子类,也就是SpringBootCondition.matches会被调用,然后它又会调用OnClassCondition.getMatchOutcome方法,然后返回结果进而得到shouldSkip方法的结果,如果是false就进行被注释类的注入,否则不注入
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
ClassLoader classLoader = context.getClassLoader();
ConditionMessage matchMessage = ConditionMessage.empty();
List<String> onClasses = this.getCandidates(metadata, ConditionalOnClass.class); //获取ConditionalOnClass注解里面写的条件类
List onMissingClasses;
if (onClasses != null) {
onMissingClasses = this.getMatches(onClasses, OnClassCondition.MatchType.MISSING, classLoader);//检查那些条件类是否存在
if (!onMissingClasses.isEmpty()) {
return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnClass.class, new Object[0]).didNotFind("required class", "required classes").items(Style.QUOTE, onMissingClasses));
}
matchMessage = matchMessage.andCondition(ConditionalOnClass.class, new Object[0]).found("required class", "required classes").items(Style.QUOTE, this.getMatches(onClasses, OnClassCondition.MatchType.PRESENT, classLoader));
}
onMissingClasses = this.getCandidates(metadata, ConditionalOnMissingClass.class);
if (onMissingClasses != null) {
List<String> present = this.getMatches(onMissingClasses, OnClassCondition.MatchType.PRESENT, classLoader);
if (!present.isEmpty()) {
return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnMissingClass.class, new Object[0]).found("unwanted class", "unwanted classes").items(Style.QUOTE, present));
}
matchMessage = matchMessage.andCondition(ConditionalOnMissingClass.class, new Object[0]).didNotFind("unwanted class", "unwanted classes").items(Style.QUOTE, this.getMatches(onMissingClasses, OnClassCondition.MatchType.MISSING, classLoader));
}
return ConditionOutcome.match(matchMessage);
}