服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - SpringBoot注解@ConditionalOnClass底层源码实现

SpringBoot注解@ConditionalOnClass底层源码实现

2023-05-29 11:35Hoeller Java教程

这篇文章主要为大家介绍了SpringBoot注解@ConditionalOnClass底层源码实现,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

@ConditionalOnClass的底层源码实现

在SpringBoot中,支持了很多种条件注解,@ConditionalOnClass注解就是其中之一,而且及其重要,它主要是用来判断该注解所指定的某个类或某些类,是否在ClassPath中存在,如果存在则符合条件,如果不存在则不符合。

?
1
2
3
4
5
6
7
8
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {
    Class<?>[] value() default {};
    String[] name() default {};
}

这是该注解的源码,可以通过value和name来指定要判断的类,而真正执行判断的逻辑在OnClassCondition类中。

  • OnClassCondition类继承了FilteringSpringBootCondition类
  • FilteringSpringBootCondition类又继承了SpringBootCondition类
  • SpringBootCondition类实现了Condition接口

SpringBoot注解@ConditionalOnClass底层源码实现

Spring在解析条件注解时,就会调用Condition接口的matches()方法,在上面的类继承关系中,SpringBootCondition类实现了matches()方法,所以会先被调用。

ConditionOutcome对象

在matches()方法中,会调用getMatchOutcome()方法,并得到ConditionOutcome对象,ConditionOutcome对象就表示条件判断的结果。

?
1
2
3
4
5
public class ConditionOutcome {
    // 表示条件是否匹配
    private final boolean match;
    // ...
}

getMatchOutcome()方法在SpringBootCondition类中是一个抽象方法,在子类OnClassCondition类中才真正实现了getMatchOutcome()方法,并真正会进行条件判断。

所以核心就是这个getMatchOutcome()方法,在这个方法中会先获取@ConditionalOnClass注解的value和name属性的值,这些值就是待判断的类名集合。

?
1
2
// 调用getCandidates方法
List<String> onClasses = getCandidates(metadata, ConditionalOnClass.class);
?
1
2
3
4
5
6
7
8
9
10
11
private List<String> getCandidates(AnnotatedTypeMetadata metadata, Class<?> annotationType) {
    MultiValueMap<String, Object> attributes =
        metadata.getAllAnnotationAttributes(annotationType.getName(), true);
    if (attributes == null) {
        return null;
    }
    List<String> candidates = new ArrayList<>();
    addAll(candidates, attributes.get("value"));
    addAll(candidates, attributes.get("name"));
    return candidates;
}

ClassNameFilter.MISSING判断某类是否不存在

接下来就会逐个判断类名集合中的每个类名,判断逻辑为:利用ClassNameFilter.MISSING来判断某类是否不存在?

?
1
List<String> missing = filter(onClasses, ClassNameFilter.MISSING, classLoader);
?
1
2
3
4
5
6
7
8
9
10
11
12
protected final List<String> filter(Collection<String> classNames, ClassNameFilter classNameFilter, ClassLoader classLoader) {
    if (CollectionUtils.isEmpty(classNames)) {
        return Collections.emptyList();
    }
    List<String> matches = new ArrayList<>(classNames.size());
    for (String candidate : classNames) {
        if (classNameFilter.matches(candidate, classLoader)) {
            matches.add(candidate);
        }
    }
    return matches;
}

ClassNameFilter.MISSING就是利用ClassLoader来加载类,如果加载到了表示类存在,没加载到就表示不存在。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
protected enum ClassNameFilter {
    // ...
    MISSING {
        @Override
        public boolean matches(String className, ClassLoader classLoader) {
                        // 是否不存在
            return !isPresent(className, classLoader);
        }
    };
    static boolean isPresent(String className, ClassLoader classLoader) {
        if (classLoader == null) {
            classLoader = ClassUtils.getDefaultClassLoader();
        }
        try {
            resolve(className, classLoader);
            return true;
        }
        catch (Throwable ex) {
            return false;
        }
    }
}
?
1
2
3
4
5
6
protected static Class<?> resolve(String className, ClassLoader classLoader) throws ClassNotFoundException {
    if (classLoader != null) {
        return Class.forName(className, false, classLoader);
    }
    return Class.forName(className);
}

判断完之后,只要missing集合不为空,那就表示待判断的类中有类不存在,那就返回条件不匹配的ConditionOutcome对象,否则就返回条件匹配的ConditionOutcome对象。

这就是@ConditionalOnClass注解的核心源码流程,期待你的点赞哦。

以上就是SpringBoot注解@ConditionalOnClass底层源码实现的详细内容,更多关于SpringBoot ConditionalOnClass的资料请关注服务器之家其它相关文章!

原文链接:https://juejin.cn/post/7106028610951053326

延伸 · 阅读

精彩推荐