条件注解:

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);
    }