SpringBoot自动装配的原理

废话不多说,直接上干货

 SpringBoot 是如何实现自动装配的?

以我这个2.6.13的版本为例

第一步,我们先从@SpringBootApplication这个入口注解看起

在springBootApplication这个注解当中有三个关键性的注解,大概可以看作是:

1,@SpringBootConfiguration        声明是个配置类
2,@EnableAutoConfiguration        负责自动配置
3,@ComponentScan                  负责包扫描

我们的重点是@EnableAutoConfiguration,因为这个才是负责spring的自动配置,

第二步,我们进入@EnableAutoConfiguration这个注解中:

@Import(AutoConfigurationImportSelector.class)这行代码是重点!

第三步,我们打开AutoConfigurationImportSelector这个类

能看到这个类实现了DeferredImportSelector接口(延迟加载的功能,也就是等其他bean定义之后来

注意:DeferredImportSelector是ImportSelector的子接口,里面有一个selectImports的方法

这个方法中的importingClassMetadata参数能拿到类上注解的信息,比如读取注解的名称、属性值等信息。

第四步,我们来到 AutoConfigurationImportSelector类的selectImports方法

@Override
/*** 决定哪些自动配置类应该被导入到Spring应用程序中。* @param annotationMetadata 当前正在处理的配置类的注解元数据。* @return 一个字符串数组,包含了应该被导入的自动配置类的全限定类名。*/
public String[] selectImports(AnnotationMetadata annotationMetadata) {// 检查是否应该启用自动配置。这通常基于特定的条件,比如类上的注解。if (!isEnabled(annotationMetadata)) {// 如果自动配置未启用,返回一个空数组,表示没有配置类需要被导入。return NO_IMPORTS;}// 获取自动配置条目,这包含了应该被导入的配置类的信息。// 这个方法会根据注解元数据和其他条件来确定这些配置类。AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);// 将配置类的列表转换为字符串数组。这是为了满足selectImports方法的返回类型要求。// StringUtils.toStringArray方法将List<String>转换为String[]。return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

第五步,我们进入getAutoConfigurationEntry这个方法

这才是自动装配的根源,接下来我们一行一行来解读

跟着我的解读,自己可以Debug一步一步看,效果会更好!

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. **检查是否启用自动配置**:
   if (!isEnabled(annotationMetadata)) {
       return EMPTY_ENTRY;
   }
这一步检查是否应该启用自动配置。`isEnabled` 方法可能会检查类上的注解(如 `@EnableAutoConfiguration`)或者类路径上的条件来决定是否启用。如果不启用,就返回一个空的 `AutoConfigurationEntry` 对象。

2. **获取注解属性**:
   AnnotationAttributes attributes = getAttributes(annotationMetadata);


   这一步获取与自动配置相关的注解属性。这些属性可能包括 `@AutoConfiguration` 注解的属性,如 `exclude` 和 `excludeName`,它们用于指定应该排除哪些自动配置类。

3. **获取候选配置**:
   List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);


   获取需要自动装配的所有配置类,读取META-INF/spring.factories文件,Spring Boot Starter 下的META-INF/spring.factories都会被读取到。

4. **去重**:
   configurations = removeDuplicates(configurations);


   这一步确保候选配置列表中没有重复的类名。这通常通过创建一个新的集合来实现,只包含之前列表中未出现过的类名。

5. **获取排除的配置**:
   Set<String> exclusions = getExclusions(annotationMetadata, attributes);


   这一步根据注解属性(如 `exclude`)获取需要排除的自动配置类的集合。

6. **检查排除的类**:
   checkExcludedClasses(configurations, exclusions);


   这一步检查排除的类是否在候选配置列表中。如果不在,可能意味着排除逻辑有误,或者是一个bug。

7. **移除排除的配置**:
   configurations.removeAll(exclusions);


   这一步从候选配置列表中移除所有在排除集合中的类名。

8. **过滤配置类**:
   configurations = getConfigurationClassFilter().filter(configurations);


   这一步使用 `ConfigurationClassFilter` 对候选配置列表进行过滤。这个过滤器可以根据@ConditionalOnxxx相关的注解,来决定哪些类应该被包含

9. **触发自动配置导入事件**:
   fireAutoConfigurationImportEvents(configurations, exclusions);


   这一步触发Spring的自动配置导入事件,允许其他组件(如监听器)在自动配置类被确定之前进行干预。

10. **创建并返回AutoConfigurationEntry对象**:
    return new AutoConfigurationEntry(configurations, exclusions);


    最后,这个方法创建一个 `AutoConfigurationEntry` 对象,它包含了最终确定的自动配置类列表和排除的类列表,并返回这个对象。这个对象随后会被Spring Boot用来加载和应用自动配置。

总的来说,这个方法是Spring Boot自动配置流程的核心部分,它负责确定哪些自动配置类应该被加载,以及哪些应该被排除。这个过程涉及到注解解析、条件检查、去重、过滤等多个步骤,以确保自动配置既准确又高效。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/702262.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java面试:Spring Cloud Alibaba

文章目录 引言I Spring Cloud Alibaba1.1 配置文件加载的优先级(由高到低)1.2 注册中心1.3 rpcII 高并发场景:缓存穿透/缓存失效/雪崩如何解决2.1 缓存穿透2.2 缓存击穿(失效)2.3 缓存雪崩引言 微服务涉及的中间件分布式事务事务的传播方式事务的隔离级别缓存穿透/缓存失效…

Matlab/simulink基于vsg的风光储调频系统建模仿真(持续更新)

​ 1.Matlab/simulink基于vsg的风光储调频系统建模仿真&#xff08;持续更新&#xff09;

C/C++暴力/枚举/穷举题目持续更新(刷蓝桥杯基础题的进!)

目录 前言 一、百钱买百鸡 二、百元兑钞 三、门牌号码&#xff08;蓝桥杯真题&#xff09; 四、相乘&#xff08;蓝桥杯真题&#xff09; 五、卡片拼数字&#xff08;蓝桥杯真题&#xff09; 六、货物摆放&#xff08;蓝桥杯真题&#xff09; 七、最短路径&#xff08;蓝…

图解目标检测 之 【YOLOv9】 算法 最全原理详解

YOLOv9与SOTA模型对比 什么是 YOLOv9&#xff1f;YOLOv9是YOLO系列中的最新产品&#xff0c;是一种实时目标检测模型。它通过先进的深度学习技术和架构设计&#xff0c;包括通用 ELAN (GELAN) 和可编程梯度信息 (PGI)&#xff0c;展现出更好的性能。 YOLO 系列通过引入计算机视…

Java/Python/Go不同开发语言基础数据结构和相关操作总结-GC篇

Java/Python/Go不同开发语言基础数据结构和相关操作总结 1. 常见gc方式1.1 gc判断对象是否存活1.2 引用计数法1.2 标记-清除算法1.3 复制算法1.4 标记-压缩算法1.5 分代收集算法 2. java的gc方式以及垃圾回收器2.1 gc方式2.1 gc回收器2.1.1 Serial收集器2.1.2 ParNew收集器2.1.…

Socket、UDP、TCP协议和简单实现基于UDP的客户端服务端

目录 Socket TCP和UDP区别 UDP&#xff1a;无连接&#xff0c;不可靠传输&#xff0c;面向数据报&#xff0c;全双工 TCP&#xff1a;有连接&#xff0c;可靠传输&#xff0c;面向字节流&#xff0c;全双工 无连接和有连接 可靠传输和不可靠传输 面向数据报和面向字节流…

学习或从事鸿蒙开发工作,有学历要求吗?

目前安卓有2,000万的开发者。本科及以上学历占比为35%&#xff1b;iOS有2,400万开发者&#xff0c;本科及以上学历占比为40% 绝大多数的前端开发者都是大专及以下学历&#xff0c;在2023年华为开发者大会上余承东透露华为的开发者目前有200万&#xff0c;但鸿蒙开发者统计的数据…

C#,数组数据波形排序(Sort in Wave Form)的朴素算法与源代码

1 波形排序 所谓“波形排序”就是一大一小。 将n个身高互不相同的人排成一行 ,对于每个人 ,要求他要么比相邻的人均高 ,要么比相邻的人均矮 ,问共有多少种排法 ,这一问题称为波形排列问题。 2 源程序 using System; using System.Collections; using System.Collections.Gen…

[嵌入式系统-33]:RT-Thread -18- 新手指南:三种不同的版本、三阶段学习路径

目录 前言&#xff1a;学习路径&#xff1a;入门学习-》进阶段学习》应用开发 一、RT-Thread版本 1.1 标准版 1.2 Nano 1.3 Smart版本 1.4 初学者制定学习路线 1.5 RT-Thread在线文档中心目录结构 1.6 学习和使用RT-Thread的三种场景 二、入门学习阶段&#xff1a;内…

信息系统项目管理师论文分享(质量管理)

水一篇文章。我发现身边考高项的朋友很多都是论文没过&#xff0c;我想着那就把我的论文分享出来&#xff0c;希望能有帮助。 质量管理 摘要 2020年5月&#xff0c;我作为项目经理参加了“某市某医联体的互联网诊疗&#xff08;互联网医院和远程医疗&#xff09;平台”的建设…

编程的基础:理解时间和空间复杂度

编程的基础&#xff1a;理解时间和空间复杂度 时间复杂度空间复杂度示例常数时间复杂度 O(1)线性时间复杂度 O(n)线性对数时间复杂度 O(n log n)二次时间复杂度 O(n^2)指数时间复杂度 O(2^n) 空间复杂度示例常数空间复杂度 O(1)线性空间复杂度 O(n)线性对数空间复杂度 O(log n)…

apache 模式、优化、功能 与 nginx优化、应用

一、I/O模型——Input/Output模型 1.同步/异步 A程序需要调用B程序的某一个功能&#xff0c;A发送一个请求需要B完成一个任务 同步&#xff1a;B不会主动去通知A是否完成需要A自己去问 异步&#xff1a;B会主动通知A是否完成 2.阻塞/非阻塞 A发送一个请求需要B完成一个任务 …

Vision Mamba:使用双向状态空间模型进行高效视觉表示学习

模型效果 将DeiT和Vim模型之间的性能和效率比较&#xff0c;为了进行准确性比较&#xff0c;我们首先在IN1K分类数据集上预训练DeiT和Vim&#xff0c;然后在不同的下游密集预测任务上微调通用主干&#xff0c;即&#xff0c;语义分割、目标检测、实例分割。结果表明&#xff0c…

Maven 私服 Nexus3

一、Maven和Nexus3 简介 Maven是一个采用纯Java编写的开源项目管理工具&#xff0c;采用一种被称之为Project Object Model(POM)概念来管理项目&#xff0c;所有的项目配置信息都被定义在一个叫做POM.xml的文件中, 通过该文件Maven可以管理项目的整个生命周期&#xff0c;包括…

2024年危险化学品经营单位主要负责人证考试题库及危险化学品经营单位主要负责人试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年危险化学品经营单位主要负责人证考试题库及危险化学品经营单位主要负责人试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特…

Ubuntu22.04和Windows10双系统安装

概要 本篇演示Ubuntu22.04和Windows10双系统的安装。先安装Ubuntu22.04&#xff0c;再安装Windows10。 一、说明 1、电脑 笔者的电脑品牌是acer(宏碁/宏基) 电脑开机按F2进入BIOS 电脑开机按F12进入Boot Manager 2、U盘启动盘 需要用到两个U盘启动盘 &#xff08;1&a…

市场复盘总结 20240223

仅用于记录当天的市场情况&#xff0c;用于统计交易策略的适用情况&#xff0c;以便程序回测 短线核心&#xff1a;不参与任何级别的调整&#xff0c;采用龙空龙模式 一支股票 10%的时候可以操作&#xff0c; 90%的时间适合空仓等待 二进三&#xff1a; 进级率中 57% 最常用的…

牛客周赛 Round 33 解题报告 | 珂学家 | 思维场

前言 整体评价 感觉这场更偏思维&#xff0c;F题毫无思路&#xff0c;但是可以模拟骗点分, E题是dij最短路. A. 小红的单词整理 类型: 签到 w1,w2 input().split() print (w2) print (w1)B. 小红煮汤圆 思路: 模拟 可以从拆包的角度去构建模拟 注意拆一包&#xff0c;可以…

vmware安装centos 7.9 操作系统

vmware安装centos 7.6 操作系统 1、下载centos 7.9 操作系统镜像文件2、安装centos 7.9 操作系统3、配置centos 7.6 操作系统3.1、配置静态IP地址 和 dns3.2、查看磁盘分区3.3、查看系统版本 1、下载centos 7.9 操作系统镜像文件 本文选择centos 7.9 最小化安装镜像包 这里选…

Nest创建神经元,并显示电压变化曲线

nest 安装与介绍 NEST&#xff08;神经模拟工具&#xff09;最初是在 1990 年代后期开发的。它的主要目标是作为计算神经科学模拟器。它支持具有不同生物学细节水平的各种神经元和突触模型。例如&#xff0c;NEST 的神经元模型范围从泄漏积分和激发模型到详细的 Hodgkin-Huxle…