SpringBoot 自动装配原理及源码解析
目录
一、引言
二、什么是 Spring Boot 的自动装配
三、自动装配的核心注解解析
3.1 @SpringBootApplication 注解
(1)@SpringBootConfiguration:
(2)@EnableAutoConfiguration:
(3)@ComponentScan:
3.2 条件装配(@Conditional 系列注解)
示例:DataSourceAutoConfiguration
四、自动配置的工作流程
五、SpringBoot 自动装配的实际案例
六、好处
一、引言
在 Java 开发领域,Spring Boot 占据着重要地位,其自动装配机制对传统开发模式产生了巨大变革。过去,传统 Spring 项目配置繁杂,极易出现版本冲突与配置错误,耗费开发者大量精力。而 Spring Boot 引入自动装配功能后,项目近乎可 “零配置” 启动,开发者能将主要精力集中于业务逻辑的实现,极大提高了开发效率。接下来,我们深入剖析 Spring Boot 自动装配背后的原理。
二、什么是 Spring Boot 的自动装配
Spring Boot 自动装配是一套智能且高效的依赖注入与配置协调系统,遵循 “约定优于配置” 的原则。在项目启动阶段,它能够自动识别类路径下的各类组件及配置信息,并依据预先设定的精细规则完成装配任务。
三、自动装配的核心注解解析
3.1 @SpringBootApplication 注解
自动配置的起点通常是 @SpringBootApplication
注解,它是一个组合注解,包含了三个重要注解。
@SpringBootApplication
public class SpringBootDemo1031Application {public static void main(String[] args) {SpringApplication.run(SpringBootDemo1031Application.class, args);}
}
(1)@SpringBootConfiguration:
本质等同于@Configuration,为自动装配的配置环节搭建基础框架,保障配置步骤有序进行
(2)@EnableAutoConfiguration:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?>[] exclude() default {};String[] excludeName() default {};
}
它是是自动配置的核心,通过@Import(AutoConfigurationImportSelector.class)引入AutoConfigurationImportSelector。
AutoConfigurationImportSelector 类的继承体系如下:
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {}public interface DeferredImportSelector extends ImportSelector {}public interface ImportSelector {String[] selectImports(AnnotationMetadata var1);
}
可以看出,AutoConfigurationImportSelector类实现了ImportSelector接口,也就实现了这个接口中的selectImports方法,该方法主要用于获取所有符合条件的类的全限类名,这些类需要被加载到IOC容器中。
public String[] selectImports(AnnotationMetadata annotationMetadata) {// 1.检查是否启用自动配置if (!this.isEnabled(annotationMetadata)) {return NO_IMPORTS;} else {// 2.获取所有需要装配的beanAutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}
}
getAutoConfigurationEntry
方法通过一系列步骤,包括检查自动配置是否启用、获取候选配置、去除重复项、获取排除配置、检查排除的类是否有效、移除排除项、过滤配置,最终生成一个包含自动配置类和排除配置类的AutoConfigurationEntry
对象。这个方法是Spring Boot自动配置功能的核心,它确保了只有符合条件的自动配置类被加载到Spring应用上下文中。
/*** 获取自动配置入口信息,包括需要加载的自动配置类和需要排除的配置类。** @param annotationMetadata 当前注解的元数据,提供了关于注解的信息,用于决定哪些自动配置类应该被导入。* @return 包含自动配置类和排除配置类的AutoConfigurationEntry对象。*/
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {// 1. 如果自动配置没有被启用,则返回一个空的AutoConfigurationEntry对象if (!this.isEnabled(annotationMetadata)) {return EMPTY_ENTRY;} else {// 2. 从注解元数据中获取注解属性AnnotationAttributes attributes = this.getAttributes(annotationMetadata);// 3. 获取所有候选的自动配置类名List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);// 4. 去除候选配置中的重复项configurations = this.removeDuplicates(configurations);// 获取需要被排除的自动配置类名Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);// 检查排除的类是否在候选配置中,如果不在,则抛出异常this.checkExcludedClasses(configurations, exclusions);// 从候选配置中移除排除项configurations.removeAll(exclusions);// 使用ConfigurationClassFilter过滤候选配置configurations = this.getConfigurationClassFilter().filter(configurations);// 触发自动配置导入事件,通知所有监听器自动配置类即将被导入this.fireAutoConfigurationImportEvents(configurations, exclusions);// 创建并返回一个新的AutoConfigurationEntry对象,包含过滤后的配置和排除配置return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);}
}
接下来,我们debug看一下具体步骤:
- 步骤1:判断自动装配开关是否打开,默认spring.boot.enableautoconfiguration=true,可以在application.properties或者application.yml中设置 。
- 步骤2:获取EnableAutoConfiguration注解中的exclude 和excluedeName
- 步骤3:获取需要自动装配的所有配置类,读取META-INF/spring.factories
自动配置类的信息通常位于
spring-boot-autoconfigure
模块的META-INF/spring.factories
文件中。这个文件列出了所有可以被自动加载的配置类,当Spring Boot应用启动时,AutoConfigurationImportSelector
会读取这个文件,并根据其中的信息将相应的自动配置类导入到应用上下文中。
-
步骤4:在spring boot中,spring.factories文件中列出了许多自动配置类,这并不意味着每次应用启动时所有这些配置都会被加载。Spring Boot采用一种称为条件配置的机制,使得只有在特定条件满足时,相关的自动配置类才会被激活和加载。
(3)@ComponentScan:
负责搜索项目中的组件,收集散落的组件,为后续装配工作提供资源支持,确保所需组件无遗漏。
3.2 条件装配(@Conditional
系列注解)
Spring Boot并非盲目加载所有自动配置类,每个自动配置类通常都会运用@Conditional系列注解来实现有条件的加载,这极大地优化了资源配置,让自动装配更贴合项目实际需求。最常见的条件注解有:
@ConditionalOnClass
:当类路径中存在某个类时才生效。@ConditionalOnMissingBean
:当 Spring 上下文中不存在某个 Bean 时才生效。@ConditionalOnProperty
:当某个配置属性满足特定条件时才生效。@ConditionalOnBean
:当 Spring 上下文中存在某个 Bean 时才生效。
示例:DataSourceAutoConfiguration
Spring Boot 中DataSourceAutoConfiguration 是配置数据源的自动配置类,它的源码如下:
@Configuration
@ConditionalOnClass(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({DataSourcePoolMetadataProvidersConfiguration.class,DataSourceInitializationConfiguration.class})
public class DataSourceAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic DataSource dataSource(DataSourceProperties properties) {return properties.initializeDataSourceBuilder().build();}
}
@ConditionalOnClass(DataSource.class)
:只有当类路径下存在DataSource
类时,才进行数据源的自动配置。@ConditionalOnMissingBean
:如果 Spring 上下文中没有其他DataSource
Bean,则自动配置一个。
只有当这些条件满足时,DataSourceAutoConfiguration才会被实例化和执行,这意味着Spring Boot在启动过程中,并不会盲目的加载spring.factories中的每一个自动配置类,而是基于运行环境和应用的配置智能选择激活配置。
四、自动配置的工作流程
1. 收集自动配置类
启动时,AutoConfigurationImportSelector
从 spring.factories
文件中读取所有的自动配置类,并通过 @Import
导入这些类。
2. 条件检查
自动配置类的加载不是无条件的,Spring Boot 会根据 @Conditional
注解进行条件检查,确保只有符合条件的自动配置类才会生效。
3. 注入所需的 Bean
一旦自动配置类通过条件检查,Spring Boot 就会根据这些配置类注册所需的 Bean。例如,DataSourceAutoConfiguration
会自动配置数据源相关的 Bean。
4. 允许用户覆盖自动配置
自动配置并不是强制的。用户可以通过显式声明自己的 Bean 来覆盖自动配置的默认行为。例如,如果用户在自己的配置类中定义了 DataSource
,那么 Spring Boot 就不会再自动配置数据源。
五、SpringBoot 自动装配的实际案例
1. Web 应用自动配置
在 Spring Boot Web 应用中,DispatcherServletAutoConfiguration
负责自动配置 Spring MVC 的核心组件,例如 DispatcherServlet
、RequestMappingHandlerMapping
等。
- 如果项目中存在
spring-web
依赖,那么DispatcherServletAutoConfiguration
会自动加载。 - 如果没有手动定义
DispatcherServlet
,Spring Boot 会自动创建一个DispatcherServlet
并配置到 Spring 容器中。
2. 数据库连接池自动配置
Spring Boot 还会自动配置数据库连接池(如 HikariCP、Tomcat JDBC 等),这依赖于项目中的 spring-boot-starter-data-jpa
或者 spring-boot-starter-jdbc
依赖。
DataSourceAutoConfiguration
和DataSourceProperties
共同负责自动配置数据源。- 如果类路径中存在连接池类(如 DruidDataSource),那么 Spring Boot 就会自动配置连接池。
六、好处
1. 提高开发效率:
开发者摆脱繁琐配置工作,无需反复查阅文档、调试配置,节省大量时间,得以聚焦业务功能迭代,在市场竞争中抢占先机。
2. 降低学习成本:
对于初涉 Spring 技术栈的新手,复杂的 Spring 配置体系曾令人望而却步。自动装配机制降低入门难度,使其无需陷入配置困境,轻松上手融入团队。
3. 保证一致性:
自动装配由 Spring Boot 框架统一管理控制,遵循统一约定,不同项目结构与配置趋于一致,便于团队协作、代码维护与知识传承,保障项目生命周期稳健延续。
总之,Spring Boot 自动装配机制为 Java 开发注入强大动力,深入理解其原理和流程,有助于开发者在开发领域游刃有余。后续可探索定制化自动装配,拓展框架应用边界,激发更多创新可能。
相关文章:

SpringBoot 自动装配原理及源码解析
目录 一、引言 二、什么是 Spring Boot 的自动装配 三、自动装配的核心注解解析 3.1 SpringBootApplication 注解 (1)SpringBootConfiguration: (2)EnableAutoConfiguration: (3…...

Craft CMS 模板注入导致 Rce漏洞复现(CVE-2024-56145)(附脚本)
0x01 产品描述: Craft CMS 是一个灵活且强大的内容管理系统(CMS),专为创意团队和开发人员设计,提供高度可定制、直观且性能优越的网站和内容管理解决方案。它以用户友好的界面、强大的插件生态系统以及支持现代web开发最佳实践的特性而闻名0x02 漏洞描述: 由于模板…...

Next.js 新手容易犯的错误 _ 加载与缓存管理的关键(5)
1 错误地处理搜索参数(Search Params) 问题是什么? 在 Next.js 中,搜索参数指的是 URL 中用 ?keyvalue 表示的部分,比如 https://example.com/products?colorred 中的 colorred。这通常用于过滤、排序或选择某些选…...

/etc/fstab 文件学习systemd与该文件关系
文章目录 一、文件字段1.1、设备标识1.2、挂载点1.3、文件系统类型1.4、挂载选项1.5、dump1.5、fsck顺序 二、/etc/fstab 与systemd 的关系2.1、/etc/fstab 与systemd 的关系2.2、systemd 之前/etc/fstab生效过程2.3、systemd 时代/etc/fstab生效过程 三、相关知识3.1、如何更具…...

从源码分析swift GCD_DispatchGroup
前言: 最近在写需求的时候用到了DispatchGroup,一直没有深入去学习,既然遇到了那么就总结下吧。。。。 基本介绍: 任务组(DispatchGroup) DispatchGroup 可以将多个任务组合在一起并且监听它们的完成状态。…...

25计软新增考研院校!或可捡漏上岸!
C哥专业提供——计软考研院校选择分析专业课备考指南规划 新增的计算机与软件工程考研院校为考研同学带来了多方面的机遇,这些机遇不仅体现在过国家线后可能面临的更低竞争压力,还包括更多元化的教育选择和更广阔的就业前景: 一、降低竞争压…...

C# 线程安全集合
文章目录 引言一、ConcurrentBag<T>二、ConcurrentQueue<T>三、ConcurrentStack<T>四、ConcurrentDictionary<TKey, TValue>五、总结引言 在多线程编程环境中,多个线程可能同时访问和操作集合数据。如果使用普通集合,很容易引发数据不一致、错误结果…...

箱包发霉怎么处理 箱包发霉处理修复方法
箱包发霉怎么处理?箱包不仅是我们出行的必需品,更是承载着个人风格与品味的时尚配饰。然而箱包工厂生产的箱包,在潮湿多变的环境中,箱包很容易成为霉菌滋生的温床,尤其是那些长时间储存的箱包,更是霉菌的“…...

【每日学点鸿蒙知识】Charles抓包、lock文件处理、WebView组件、NFC相关、CallMethod失败等
1、HarmonyOS系统中如何使用Charles抓包? 在HarmonyOS操作系统中,使用Charles进行抓包的步骤如下: 在Charles中设置代理。 首先,在Charles的菜单栏上选择“Proxy”→“Proxy Settings”,然后填入代理端口࿰…...

【异常】GL-SFT1200路由器中继模式,TL-CPE1300D无法搜寻5G网问题分析
【异常】GL-SFT1200路由器中继模式,TL-CPE1300D无法搜寻5G网问题 情况实验结论情况 在用GL-SFT1200路由器切换中继模式时,由于web密码忘却,需要重置,但根据官网使用手册,或者对应的中文版手册,重置失败。通过跟商家联系,进行uboot刷机,提供了指导文档,尝试后刷机成功…...

LINUX--shell
函数 格式: func() { command } function 关键字可写,也可不写。 示例 1: #!/bin/bash func() { #定义函数 echo "Hello $1" } func world #执行主文件 # bash test.sh Hello world 数组 数组是相…...

TCP常见问题
文章目录 一、两种状态图二、常见问题1、MSL是什么 3、为何等待2MSL3、为何三次握手,不握手、握手一次、两次行吗4、为何四次挥手,三次行吗,两次行吗 一、两种状态图 四次挥手 二、常见问题 1、MSL是什么 MSL是Maximum Segment Lifetime的英…...

OpenCV学习——图像融合
import cv2 as cv import cv2 as cvbg cv.imread("test_images/background.jpg", cv.IMREAD_COLOR) fg cv.imread("test_images/forground.png", cv.IMREAD_COLOR)# 打印图片尺寸 print(bg.shape) print(fg.shape)resize_size (1200, 800)bg cv.resize…...

网速、续航双在线!2024随身WiFi品牌精选推荐!格行按键切三网值得买吗?
随身wifi这个东西大家用的还是蛮多的,特别是一些户外工作的人员,往往都需要配备一个随身wifi,这样户外工作的时候才有网络,工作才会比较方便一些。今天就来盘点2024年热门随身wifi哪个牌子的好用? 1.华为:通…...

ubuntu18.04连接不上网络问题
现象:右上角的网络图标消失,仅剩输入法、音量和开关图标,ifconfig只显示本地回环 原因:网络适配器未开启 解决: 1. 查看网络状态:cat /var/lib/NetworkManager/NetworkManager.state 这里显示是false&a…...

访谈积鼎科技总经理:国产CFD软件发展与未来趋势展望
傅彦国,上海积鼎信息科技有限公司创始人 记者:请傅总介绍下我国流体仿真行业的发展现状是怎样的? 傅彦国:自2018年政府加大了对核心技术自主研发的支持力度,国产CFD软件逐渐步入发展正轨。 首先,从市场规…...

【Linux知识】exec命令行详解
文章目录 概述主要用途和 bash 有什么区别? 概述 在 Linux 系统中,exec 命令用于执行一个可执行文件,替换当前进程的映像。也就是说,当你在终端中使用 exec 命令后,当前的 shell 会被替换为 exec 指定的程序ÿ…...

【学术小白的学习之路】基于情感词典的中文句子情感分析(代码词典获取在结尾)
【学术小白的学习之路】基于情感词典的情感分析 1.基础函数1.1 判断情感词的否定词数量1.2 导入情感词典1.3 切分句子1.3.1为什么划分1.3.2 划分代码 1.4 完整代码 2.导入词典3.中文情感分析算法思路4.1情感词获取思路4.2 计算情感分值4.3 得分的归一化处理 4.实证5.总结 本文的…...

Linux 中 grep、sed、awk 命令
1. awk:强大的文本分析工具 awk,全称“Awk语言”,是一种专门用于处理文本文件的语言。它不仅能够根据关键字匹配某一行,还能进行复杂的文本分析和处理。awk的语法简洁明了,功能强大,是文本处理领域的佼佼者…...

一起考高项啊--现代化基础设施(工业互联网)
1、工业互联网的内涵和外延 工业互联网不是互联网在工作的简单应用,是具有更为丰富的内涵和外延。 它既是工业数字化、网络化、智能化转型的基础设施,也是互联网、大数据、人工智能与实体经济深度融合的应用模式,同时也是一种新业态、新产业…...

python学opencv|读取图像(二十)使用cv2.circle()绘制圆形进阶
【1】引言 前序已经掌握了使用cv2.circle()绘制圆形的基本操作,相关链接为: python学opencv|读取图像(二十)使用cv2.circle()绘制圆形-CSDN博客 由于圆形本身绘制起来比较简单,因此可以自由操作的空间也就大&#x…...

期权懂|如何减小个股期权交易中的风险?
锦鲤三三每日分享期权知识,帮助期权新手及时有效地掌握即市趋势与新资讯! 如何减小个股期权交易中的风险? 一、选择合适的期权合约 (1)选择活跃的期权合约:投资者应优先选择交易活跃的期权合约。交易活跃的…...

ubuntu20.04 wget下载--段错误 (核心已转储)
用wget下载时总是在快下载完成时遇到段错误 untu2004-9.1.0_1.0-1_am 99%[> ] 1.63G 3.11MB/s 剩余 1s s段错误 (核心已转储)有以下两种解决方法: 1.手动下载 wget后面就是要下载的资源的链接,直接复制到浏览器中下载即可 如:…...

怎么样保持mysql和redis数据一致性
保持 MySQL 和 Redis 数据的一致性是一个常见的挑战,因为 MySQL 是传统的关系型数据库,而 Redis 是内存数据库,通常用于缓存和高性能存储。这两者的数据更新方式不同,特别是当 Redis 用作缓存时,可能会存在缓存和数据库之间的数据不一致问题。为了保持数据一致性,通常可以…...

剑指Offer|LCR 013. 二维区域和检索 - 矩阵不可变
LCR 013. 二维区域和检索 - 矩阵不可变 给定一个二维矩阵 matrix,以下类型的多个请求: 计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2) 。 实现 NumMatrix 类: NumMatrix(…...

aosp15 - Activity生命周期切换
本文探查的是,从App冷启动后到MainActivity生命周期切换的系统实现。 调试步骤 在com.android.server.wm.RootWindowContainer#attachApplication 方法下断点,为了attach目标进程在com.android.server.wm.ActivityTaskSupervisor#realStartActivityLock…...

vxe-table 虚拟滚动的动态响应
虚拟滚动主要是在有限范围内渲染想要显示的数据,主要体现在懒加载数据和动态渲染上。如何提高虚拟滚动的操作性呢?请看本章解析 1.什么是虚拟滚动?代码如何实现? VXE-Table提供了一种名为“虚拟滚动”的功能,该功能可…...

quasar dev 命令卡住很久
别以为这是一个瞬间的截图,其实停留在这里很久很久。 折腾挺久,无论npm run dev:proxy还是 quasar dev,都是一样的情况。 最终解决办法: 有语法问题,通过 quasar build 命令暴露出来错误所在的行数。...

黑盒RCE测试 异或测试
前言 了解了漏洞的原理之后就需要知道 他在哪能出现 并且被利用 这个还是很重要的 异或测试 使用异或(XOR)运算进行加密解密的原理_异或加密-CSDN博客 异或测试是在 白盒内执行的 一个例题看一下 输入什么都是会报错 这种情况就需要使用 异或计…...

kotlin中泛型中in和out的区别
概念含义 in关键字(逆变) 在Kotlin泛型中,in关键字主要用于定义逆变(Contravariance)。它表示一个泛型类型参数可以是指定类型或者它的超类型。简单来说,就是对于类型A和B,如果A是B的子类型&…...