【Spring Boot 源码学习】自动装配流程源码解析(上)

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

《Spring Boot 源码学习系列》

【Spring Boot 源码学习】自动装配流程源码解析(上),开发框架-Spring Boot,spring boot,自动装配流程,加载自动装配

引言

上篇博文,笔者带大家从整体上了解了AutoConfigurationImportSelector 自动装配逻辑的核心功能及流程,由于篇幅有限,更加细化的功能及流程详解还没有介绍。本篇开始将从其源码入手,重点解析细化后的自动装配流程源码。

往期内容

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

Spring Boot 源码学习
Spring Boot 项目介绍
Spring Boot 核心运行原理介绍
【Spring Boot 源码学习】@EnableAutoConfiguration 注解
【Spring Boot 源码学习】@SpringBootApplication 注解
【Spring Boot 源码学习】走近 AutoConfigurationImportSelector

主要内容

下面就让我们从 AutoConfigurationImportSelectorselectImports 方法源码入手,开始了解自动装配流程。

下面来看一下 selectImports 的相关源码【Spring Boot 2.7.9】:

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
	if (!isEnabled(annotationMetadata)) {
		return NO_IMPORTS;
	}
	AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
	return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
	if (!isEnabled(annotationMetadata)) {
		return EMPTY_ENTRY;
	}
	AnnotationAttributes attributes = getAttributes(annotationMetadata);
	List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
	configurations = removeDuplicates(configurations);
	Set<String> exclusions = getExclusions(annotationMetadata, attributes);
	checkExcludedClasses(configurations, exclusions);
	configurations.removeAll(exclusions);
	configurations = getConfigurationClassFilter().filter(configurations);
	fireAutoConfigurationImportEvents(configurations, exclusions);
	return new AutoConfigurationEntry(configurations, exclusions);
}

1. 自动配置开关

检查自动配置是否开启的逻辑位于 AutoConfigurationImportSelectorselectImports 方法中的第一段代码。如果开启自动配置,则继续执行后续操作;否则就返回空数组。

检查自动配置是否开启的源码,如下所示:

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
	if (!isEnabled(annotationMetadata)) {
      	return NO_IMPORTS;
   	}
	// ...省略
}

从上面的源码可以看出,这里主要使用了 isEnabled 方法来判断自动配置是否开启;其中该方法返回 true,表示开启自动配置,返回 false,表示关闭自动配置。

我们来看一下它的源码,如下所示:

protected boolean isEnabled(AnnotationMetadata metadata) {
	if (getClass() == AutoConfigurationImportSelector.class) {
		return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
	}
	return true;
}

通过阅读上述 isEnabled 方法源码,我们可以看出,如果当前类为 AutoConfigurationImportSelector,会从环境中获取 keyEnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY 的配置属性,而笔者前面的系列博文如果大家看过的话,介绍 EnableAutoConfiguration 注解时,就说了这个常量的值为 spring.boot.enableautoconfiguration

【Spring Boot 源码学习】自动装配流程源码解析(上),开发框架-Spring Boot,spring boot,自动装配流程,加载自动装配

如果该属性的配置获取不到,则默认为 true,也就是默认会开启自动配置。如果当前类为其他类,也则默认直接返回 true

如果想覆盖或重置该配置,我们可以在 application.propertiesapplication.yml 中针对 spring.boot.enableautoconfiguration 参数进行配置。

application.properties 配置关闭自动配置为例,如下所示 :

spring.boot.enableautoconfiguration=false

2. 加载自动配置组件

接下来,我们看到调用 getAutoConfigurationEntry 的代码,它是用来封装将被引入的自动配置信息:

AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);

然后我们进入 getAutoConfigurationEntry 方法,看到了获取注解属性的逻辑,如下所示:

AnnotationAttributes attributes = getAttributes(annotationMetadata);

// 从 AnnotationMetadata 返回适当的 AnnotationAttributes。默认情况下,此方法将返回 getAnnotationClass() 的属性。
protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
	String name = getAnnotationClass().getName();
	AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(name, true));
	Assert.notNull(attributes, () -> "No auto-configuration attributes found. Is " + metadata.getClassName()
			+ " annotated with " + ClassUtils.getShortName(name) + "?");
	return attributes;
}

我们启动先前建的 Spring Boot 项目的应用类,在 getAttributes 方法最后 return 处打个断点,我们可以看到如下的逻辑:

【Spring Boot 源码学习】自动装配流程源码解析(上),开发框架-Spring Boot,spring boot,自动装配流程,加载自动装配

了解到这,可以开始加载自动配置的组件了,也就是下面的代码:

// 通过 SpringFactoriesLoader 类提供的方法加载类路径中META-INF目录下的
// spring.factories文件中针对 EnableAutoConfiguration 的注解配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);

我们进入 getCandidateConfigurations 方法中, 相关源码如下所示:

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
	List<String> configurations = new ArrayList<>(
			SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
	ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);
	Assert.notEmpty(configurations,
			"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
					+ "are using a custom packaging, make sure that file is correct.");
	return configurations;
}

通过阅读上述源码,我们可以看出这里使用了 SpringFactoriesLoader 类提供的loadFactoryNames 方法来加载的。其中 loadFactoryNames 方法的第一个参数为 getSpringFactoriesLoaderFactoryClass 方法返回的 EnableAutoConfiguration.class

protected Class<?> getSpringFactoriesLoaderFactoryClass() {
	return EnableAutoConfiguration.class;
}

通过翻看 loadFactoryNames 方法对应的源码,我们可以知道它是读取的 META-INF/spring.factories 中的配置,并且只会读取配置文件中针对自动配置的注册类【即 EnableAutoConfiguration 相关的配置信息】。

SpringFactoriesLoader 类的 loadFactoryNames 方法相关源码,由于篇幅有限,这里就不贴出来了,感兴趣的朋友可以自行查阅,Spring Boot 中后续会有很多地方用到它,比如用于监听的 Listeners 和用于过滤的 Filters

实际上 在 Spring Boot 2.7.9 版本中, 它自己内部的 META-INF/spring.factories 中有关自动配置的注册类的配置信息已经被去除掉了,不过其他外围的 jar 中可能有自己的 META-INF/spring.factories 文件,它里面也有关于自动配置注册类的配置信息;

另外我们在 getCandidateConfigurations 方法中,也看到了另一行代码获取自动配置注册类的信息,如下所示:

ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);

这里的代码其实就是读取的如下截图的配置信息【同 META-INF/spring.factories 一样,下面的配置也可能存在于不同的 jar 包中 】:

【Spring Boot 源码学习】自动装配流程源码解析(上),开发框架-Spring Boot,spring boot,自动装配流程,加载自动装配

我们启动先前建的 Spring Boot 项目的应用类,在 getCandidateConfigurations 方法 ImportCandidates 类调用处打个断点,我们可以看到如下的截图【这里 configurations 目前还是空数据,说明从 META-INF/spring.factories 没有获取到自动配置注册类的相关信息,因为我们只引入了 Spring Boot 项目,并且它内部的 META-INF/spring.factories 中的确删除了自动配置注册类的相关信息】:

【Spring Boot 源码学习】自动装配流程源码解析(上),开发框架-Spring Boot,spring boot,自动装配流程,加载自动装配

getCandidateConfigurations 方法 最后 return 处打个断点,我们可以看到如下的截图【这里 configurations 中加载的都是自动配置的注册类,也就是 上述 ImportCandidates##load 加载的信息,这里读取的是 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中的配置信息】:

【Spring Boot 源码学习】自动装配流程源码解析(上),开发框架-Spring Boot,spring boot,自动装配流程,加载自动装配

3. 自动配置组件去重

因为上述加载的自动配置注册类,默认加载的是 ClassLoader 下面的所有 META-INF/spring.factoriesMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中的配置,所以就有可能出现在不同的jar包中有重复配置的情况。

Spring Boot 中则使用了 Java 中 Set 集合数据不可重复的特点,来实现去重处理,如下所示:

// 对获得的注解配置类集合进行去重处理,防止多个项目引入同样的配置类
configurations = removeDuplicates(configurations);

// 利用 Set 集合数据不可重复的特点,来实现去重处理
protected final <T> List<T> removeDuplicates(List<T> list) {
	return new ArrayList<>(new LinkedHashSet<>(list));
}	

总结

本篇 Huazie 带大家通读了 Spring Boot 自动装配逻辑的部分源码,详细分析了加载自动装配的流程,剩下排除和过滤自动配置的流程将在下一篇继续讲解。内容较多,能够看到这的小伙伴,Huazie 在这感谢各位的支持。后续我将持续输出有关 Spring Boot 源码学习系列的博文,想要及时了解更新的朋友,订阅这里即可。文章来源地址https://www.toymoban.com/news/detail-629958.html

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

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

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

相关文章

  • Spring Boot自动装配

    自动装配是 Spring Boot 最核心的功能之一,第三方可以基于这个特性非常方便的和 Spring 做整合,实现自己的 Starter,做到开箱即用。 Java 早期并不支持注解,所以那会儿 Spring 只能通过 xml 的形式来配置。早期项目里要引入一个功能模块,首先我们要引入 SDK,然后在 xml 里配置

    2024年01月23日
    浏览(32)
  • Spring Boot 自动装配原理

    Java面试题目录 Spring Boot自动装配原理   Spring Boot启动类上的 @SpringBootApplication 注解中包含 @EnableAutoConfiguration 注解,表示开启自动装配。在@EnableAutoConfiguration注解中使用@Import注解引入 AutoConfigurationImportSelector 组件,此类中通过 SpringFactoriesLoader.loadFactoryNames() 方法来扫描所有

    2024年01月25日
    浏览(31)
  • 深入了解Spring Boot自动装配

    Spring Boot的自动装配是一项强大的功能,能够简化应用程序的配置和开发过程。让我们通过一系列详细的例子来深入了解这一特性。 在Spring Boot中,自动装配是指框架根据应用程序的依赖关系,自动配置和装配相应的Bean,而无需手动设置。这使得开发者可以更专注于业务逻辑

    2024年01月23日
    浏览(32)
  • Spring Boot如何实现自动装配

    Spring Boot的自动装配是它的一大特点,可以大大提高开发效率,减少重复性代码的编写。本文将详细讲解Spring Boot如何实现自动装配。 在传统的Spring框架中,我们需要手动配置和管理Bean的依赖关系,但在Spring Boot中,大量的配置可以自动完成。这是因为Spring Boot中引入了自动装

    2024年02月04日
    浏览(31)
  • Spring Boot自动装配原理(易懂)

    熟练使用Spring Boot那么自动装配原理的掌握是必不可少的 Spring Boot的自动装配实际上是从 META-INF/spring.factories 文件中获取到对应的需要进行自动装配的类,并生成相应的Bean对象,然后将它们交给Spring容器进行管理 启动类的@SpringBootAppliation注解是一个组合注解,由以下3个注解组

    2024年02月16日
    浏览(31)
  • spring boot的自动装配原理

    作者: 逍遥Sean 简介:一个主修Java的Web网站游戏服务器后端开发者 主页:https://blog.csdn.net/Ureliable 觉得博主文章不错的话,可以三连支持一下~ 如有需要我的支持,请私信或评论留言! Spring Boot是一个开源的Java框架,可以帮助开发者快速构建基于Spring的应用程序。Spring Boo

    2024年02月10日
    浏览(27)
  • Spring Boot中自动装配机制的原理

    1 .自动装配,简单来说就是自动把第三方组件的Bean装载到Spring IOC容器里面 ,不需要开发人员再去写Bean的装配配置, 2.在Spring Boot应用里面,只需要在启动类加上 @SpringBootApplication 注解就可以实现自动装配。 3.@SpringBootApplication是一个复合注解, 真正实现自动装配的注解是@

    2024年02月10日
    浏览(25)
  • redisson-spring-boot-starter 自动化配置源码解析

    redisson-spring-boot-starter:3.25.2 此starter会自动注册RedissonClient Bean 并可通过注册RedissonAutoConfigurationCustomizer Bean实现配置自定义 spring-boot:2.7以上 org.redisson.spring.starter.RedissonAutoConfigurationV2 spring-boot:2.6以下 org.redisson.spring.starter.RedissonAutoConfiguration

    2024年01月17日
    浏览(71)
  • Spring retry(二)- 源码解析-启动装配篇 @EnableRetry

    上一篇文章,我们快速介绍了下spring-retry的使用技巧,本篇我们将会剖析源码去学习 英文翻译我就不再解释了,上面说的很清楚;这里重点提一下@Import(RetryConfiguration.class)这个注解,表明了@EnableRetry注解的启动配置类是RetryConfiguration, 通过@Import注解来注入对应的配置类,这

    2024年02月10日
    浏览(29)
  • 深入解析 Spring 的 @Autowired:自动装配的魔法与细节

    @Autowired 是 Spring 框架中的一个重要注解,用于自动装配 bean 依赖。Spring 通过 @Autowired 可以自动将匹配的 bean 注入到需要的地方,如属性、构造函数或 setter 方法等。 下面是 @Autowired 注解的详细说明: 作用 自动装配 : @Autowired 注解能够自动装配 Spring 容器中的 bean,使得开发

    2024年02月03日
    浏览(31)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包