【Spring Boot 源码学习】深入 FilteringSpringBootCondition

这篇具有很好参考价值的文章主要介绍了【Spring Boot 源码学习】深入 FilteringSpringBootCondition。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Spring Boot 源码学习系列

【Spring Boot 源码学习】深入 FilteringSpringBootCondition,开发框架-Spring Boot,Spring Boot,源码学习,自动配置过滤匹配父类,ClassNameFilter

引言

前两篇博文笔者带大家从源码深入了解了 Spring Boot 的自动装配流程,其中自动配置过滤的实现由于篇幅限制,还未深入分析。

那么从本篇开始,Huazie 就带大家走近 AutoConfigurationImportFilter,一起从源码解析 FilteringSpringBootConditionOnBeanConditionOnClassConditionOnWebApplicationCondition 的实现。

往期内容

在开始本篇的内容介绍之前,我们先来看看往期的系列文章【有需要的朋友,欢迎关注系列专栏】:

Spring Boot 源码学习
Spring Boot 项目介绍
Spring Boot 核心运行原理介绍
【Spring Boot 源码学习】@EnableAutoConfiguration 注解
【Spring Boot 源码学习】@SpringBootApplication 注解
【Spring Boot 源码学习】走近 AutoConfigurationImportSelector
【Spring Boot 源码学习】自动装配流程源码解析(上)
【Spring Boot 源码学习】自动装配流程源码解析(下)

主要内容

在开始本篇内容之前,我们再次来回顾一下上篇博文介绍的 AutoConfigurationImportFilter 的源码和相关的类图:

@FunctionalInterface
public interface AutoConfigurationImportFilter {
	// 自动配置组件的过滤匹配
	boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata);
}

【Spring Boot 源码学习】深入 FilteringSpringBootCondition,开发框架-Spring Boot,Spring Boot,源码学习,自动配置过滤匹配父类,ClassNameFilter

通过上面的关联类图,我们可以看到 AutoConfigurationImportFilter 接口实际上是由抽象类 FilteringSpringBootCondition 来实现的,另外翻看它的源码,该抽象类还定义了一个抽象方法 getOutcomes ,然后 OnBeanConditionOnClassConditionOnWebApplicationCondition 继承该抽象类,实现 getOutcomes 方法,完成实际的过滤匹配操作。

本篇,我们就从源码入手重点介绍 FilteringSpringBootCondition

1. match 方法

上一篇博文我们已经从 FilteringSpringBootCondition 的部分源码进行了分析,它的 match 方法主要是调用 getOutcomes 方法,并将其返回的结果转换成布尔数组。而这个 getOutcomes 方法是过滤匹配的核心功能,由抽象类 FilteringSpringBootCondition 的子类来实现它。

这里再简单回顾一下 match 方法的处理逻辑:

@Override
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
	ConditionEvaluationReport report = ConditionEvaluationReport.find(this.beanFactory);
	// 调用 由子类实现的 getOutcomes 方法,完成实际的过滤匹配操作
	ConditionOutcome[] outcomes = getOutcomes(autoConfigurationClasses, autoConfigurationMetadata);
	boolean[] match = new boolean[outcomes.length];
	// 将 getOutcomes 方法返回结果转换成布尔数组
	for (int i = 0; i < outcomes.length; i++) {
		match[i] = (outcomes[i] == null || outcomes[i].isMatch());
		if (!match[i] && outcomes[i] != null) {
			logOutcome(autoConfigurationClasses[i], outcomes[i]);
			if (report != null) {
				report.recordConditionEvaluation(autoConfigurationClasses[i], this, outcomes[i]);
			}
		}
	}
	return match;
}

上述代码中,我们可以看到,将 getOutcomes 方法返回结果转换成布尔数组的循环逻辑中有一段代码如下:

match[i] = (outcomes[i] == null || outcomes[i].isMatch());

这里是将返回结果转换成布尔值,分别是:

  • 如果匹配结果为 null ,认为符合匹配要求, 设置 match[i] = true
  • 如果匹配结果不为 null,并且 匹配对象的 isMatch == true,也认为符合匹配要求, 设置 match[i] = true

这个时候,我们就能理解 上篇博文讲到的 不符合过滤匹配要求,则清空当前的自动配置组件 的逻辑:
【Spring Boot 源码学习】深入 FilteringSpringBootCondition,开发框架-Spring Boot,Spring Boot,源码学习,自动配置过滤匹配父类,ClassNameFilter

当然 FilteringSpringBootCondition 内还有其他的内容,这些内容在它的子类中也将使用到,我们先提前了解下,以便后续能更好地理解子类的功能实现。

2. ClassNameFilter 枚举类

首先查看 ClassNameFilter 枚举类的源码【Spring Boot 2.7.9】:

protected enum ClassNameFilter {

	PRESENT {

		@Override
		public boolean matches(String className, ClassLoader classLoader) {
			return isPresent(className, classLoader);
		}

	},

	MISSING {

		@Override
		public boolean matches(String className, ClassLoader classLoader) {
			return !isPresent(className, classLoader);
		}

	};

	abstract boolean matches(String className, ClassLoader classLoader);

	// ....

}

ClassNameFilter 枚举类包含两个枚举常量,分别是 PRESENTMISSING;这两个枚举常量都实现了 ClassNameFilter 枚举类定义的 matches 的抽象方法,其中

  • PRESENT 中的 matches 返回 isPresent(className, classLoader);
  • MISSING 中的 matches 返回 !isPresent(className, classLoader);

我们继续看 isPresent 方法,分析一下它的功能:

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

上述 isPresent 方法的逻辑其实也并不复杂,就是通过类加载器去加载指定的类【即 className 字符串对应的类】:

  • 如果指定的类加载成功,则直接返回 true
  • 如果指定的类加载失败,则要抛出异常,捕获异常后,返回 false

那显然 ClassNameFilter.PRESENT.matches(className, classLoader) 用于校验指定的类是否加载成功

  • 如果指定的类加载成功,则返回 true
  • 如果指定的类加载失败,则返回 false

ClassNameFilter.MISSING.matches(className, classLoader) 用于校验指定的类是否加载失败

  • 如果指定的类加载失败,则返回 true
  • 如果指定的类加载成功,则返回 false

3. filter 方法

继续翻看 FilteringSpringBootCondition 源码,还有一个 filter 方法需要重点介绍下:

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 枚举类,我们可以很容易理解上面的代码逻辑。

  • 如果 classNameFilterClassNameFilter.PRESENT,则 filter 方法获取指定的类集合中加载成功的类集合【即匹配成功的类集合】;
  • 如果 classNameFilterClassNameFilter.MISSING,则 filter 方法获取指定的类集合中加载失败的类集合【即匹配失败的类集合】。

总结

本篇 Huazie 带大家介绍了自动配置过滤匹配的核心父类 FilteringSpringBootCondition,这对于笔者后续博文详解它的三个子类【OnBeanConditionOnClassConditionOnWebApplicationCondition】非常重要,敬请期待!!!。文章来源地址https://www.toymoban.com/news/detail-706983.html

到了这里,关于【Spring Boot 源码学习】深入 FilteringSpringBootCondition的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Spring Boot 源码学习】BootstrapRegistryInitializer 详解

    《Spring Boot 源码学习系列》 书接前文《初识 SpringApplication》,我们从 Spring Boot 的启动类 SpringApplication 上入手,了解了 SpringApplication 实例化过程。其中,有如下三块内容还未详细分析: 本篇博文就主要围绕 2.3 的内容展开,详细分析一下加载并初始化 BootstrapRegistryInitializer

    2024年02月04日
    浏览(28)
  • 【Spring Boot 源码学习】走近 AutoConfigurationImportSelector

    《Spring Boot 源码学习系列》 上篇博文我们了解了 @EnableAutoConfiguration 注解,其中真正实现自动配置功能的核心实现者 AutoConfigurationImportSelector 还没有详细说明,本篇将从它的源码入手来重点介绍。 在介绍 AutoConfigurationImportSelector 之前,有必要了解下它所实现的 ImportSelector 接

    2024年02月12日
    浏览(22)
  • 【Spring Boot 源码学习】JedisConnectionConfiguration 详解

    《Spring Boot 源码学习系列》 上篇博文, Huazie 带大家从源码角度分析了 Spring Boot 内置的有关 Redis 的自动配置类【 RedisAutoConfiguration 】,其中有关 LettuceConnectionConfiguration 和 JedisConnectionConfiguration 这两个用于配置 Redis 连接的具体实现还未介绍。本篇就以我们常用的 Jedis 实现

    2024年02月05日
    浏览(34)
  • 【Spring Boot 源码学习】BootstrapRegistry 详解

    《Spring Boot 源码学习系列》 前面的博文《BootstrapRegistryInitializer 详解》,Huazie 带大家一起详细分析了 Spring Boot 启动时加载并初始化 BootstrapRegistryInitializer 及其相关的类的逻辑。其中有个 BootstrapRegistry 接口只是简单提及,本篇就详细分析一下 BootstrapRegistry 接口,这对于我们后

    2024年02月20日
    浏览(27)
  • 【Spring Boot 源码学习】RedisAutoConfiguration 详解

    《Spring Boot 源码学习系列》 上篇博文, Huazie 带大家从源码角度分析了 Spring Boot 内置的 http 编码功能,进一步熟悉了自动配置的装配流程。本篇趁热打铁,继续带大家分析 Spring Boot 内置的有关 Redis 的自动配置类【 RedisAutoConfiguration 】。 在开始本篇的内容介绍之前,我们先来

    2024年02月07日
    浏览(28)
  • 【Spring Boot 源码学习】初识 SpringApplication

    《Spring Boot 源码学习系列》 往期的博文, Huazie 围绕 Spring Boot 的核心功能,带大家从总整体上了解 Spring Boot 自动配置的原理以及自动配置核心组件的运作过程。这些内容大家需要重点关注,只有了解这些基础的组件和功能,我们在后续集成其他三方类库的 Starters 时,才能够

    2024年02月05日
    浏览(30)
  • 【Spring Boot 源码学习】OnWebApplicationCondition 详解

    《Spring Boot 源码学习系列》 上篇博文带大家从 Spring Boot 源码深入详解了 OnBeanCondition ,那本篇也同样从源码入手,带大家深入了解 OnWebApplicationCondition 的过滤匹配实现。 在开始本篇的内容介绍之前,我们先来看看往期的系列文章【有需要的朋友,欢迎关注系列专栏】: Spr

    2024年02月08日
    浏览(28)
  • 【Spring Boot 源码学习】HttpEncodingAutoConfiguration 详解

    Spring Boot 源码学习系列 前面的博文,我们从源码角度介绍了自动装配流程。虽然带大家从整体上有了清晰的认识,但是我们还不能熟练地运用。本篇就以 Spring Boot 内置的 http 编码功能为例,来带大家分析一下 HttpEncodingAutoConfiguration 的整个自动配置的过程。 在开始本篇的内容

    2024年02月08日
    浏览(28)
  • 【Spring Boot 源码学习】@Conditional 条件注解

    《Spring Boot 源码学习系列》 前面的博文,Huazie 带大家从 Spring Boot 源码深入了解了自动配置类的读取和筛选的过程,然后又详解了 OnClassCondition 、 OnBeanCondition 、 OnWebApplicationCondition 这三个自动配置过滤匹配子类实现。 在上述的博文中,我们其实已经初步涉及到了像 @Conditi

    2024年02月07日
    浏览(30)
  • 【Spring Boot 源码学习】BootstrapContext的实际使用场景

    《Spring Boot 源码学习系列》 上一篇博文《BootstrapRegistry 初始化器实现》, Huazie 向大家介绍了如何自定义 BootstrapRegistryInitializer 接口实现,并以此来执行自定义的初始化操作【如注册自定义的 Bean 、添加 BootstrapContext 关闭监听器】。其中涉及到了 BootstrapContext 的部分使用场景

    2024年03月11日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包