SpringBoot注解@ConditionalOnClass底层源码实现

2023-05-30 0 2,975

目录

@ConditionalOnClass底层源码实现

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

@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对象就表示条件判断的结果。

public class ConditionOutcome {
	// 表示条件是否匹配
	private final boolean match;
	// ...
}

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

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

// 调用getCandidates方法
List<String> onClasses = getCandidates(metadata, ConditionalOnClass.class);
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来判断某类是否不存在?

List<String> missing = filter(onClasses, ClassNameFilter.MISSING, classLoader);
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来加载类,如果加载到了表示类存在,没加载到就表示不存在。

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;
		}
	}
}
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的资料请关注其它相关文章!

资源下载此资源下载价格为1小猪币,终身VIP免费,请先
由于本站资源来源于互联网,以研究交流为目的,所有仅供大家参考、学习,不存在任何商业目的与商业用途,如资源存在BUG以及其他任何问题,请自行解决,本站不提供技术服务! 由于资源为虚拟可复制性,下载后不予退积分和退款,谢谢您的支持!如遇到失效或错误的下载链接请联系客服QQ:442469558

:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可, 转载请附上原文出处链接。
1、本站提供的源码不保证资源的完整性以及安全性,不附带任何技术服务!
2、本站提供的模板、软件工具等其他资源,均不包含技术服务,请大家谅解!
3、本站提供的资源仅供下载者参考学习,请勿用于任何商业用途,请24小时内删除!
4、如需商用,请购买正版,由于未及时购买正版发生的侵权行为,与本站无关。
5、本站部分资源存放于百度网盘或其他网盘中,请提前注册好百度网盘账号,下载安装百度网盘客户端或其他网盘客户端进行下载;
6、本站部分资源文件是经压缩后的,请下载后安装解压软件,推荐使用WinRAR和7-Zip解压软件。
7、如果本站提供的资源侵犯到了您的权益,请邮件联系: 442469558@qq.com 进行处理!

猪小侠源码-最新源码下载平台 Java教程 SpringBoot注解@ConditionalOnClass底层源码实现 https://www.20zxx.cn/763401/xuexijiaocheng/javajc.html

猪小侠源码,优质资源分享网

常见问题
  • 本站所有资源版权均属于原作者所有,均只能用于参考学习,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,建议提前注册好百度网盘账号,使用百度网盘客户端下载
查看详情

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务