Spring之我见 - Spring Boot Starter 自动装配原理
欢迎光临小站:致橡树
Spring Boot Starter 的核心设计理念是 约定优于配置,其核心实现基于 自动配置(Auto-Configuration) 和 条件化注册(Conditional Registration)。以下是其生效原理:
约定大于配置
通过预定义合理的默认行为和规范,减少开发者需要手动配置的步骤。比较显著的变化就是减少XML配置。还有一些实际体现如下所示:
-
项目结构约定
-
默认目录结构:如
src/main/java
存放代码,src/main/resources
存放配置文件。 -
配置文件命名:
application.properties
或application.yml
自动被加载,无需显式指定路径。
-
-
自动配置(Auto-Configuration)
-
条件化 Bean 注册:根据类路径依赖(如存在
DataSource
类)自动配置数据库连接池。 -
默认参数值:如嵌入式 Tomcat 默认端口为
8080
,无需手动指定。
-
-
Starter 依赖
-
依赖聚合:引入
spring-boot-starter-web
即自动包含 Web 开发所需的所有依赖(如 Tomcat、Jackson、Spring MVC)。 -
开箱即用:无需手动管理版本兼容性。
-
-
RESTful 路由映射
-
注解驱动:通过
@GetMapping("/path")
即可定义接口,无需在 XML 中配置路由规则。
-
自动配置机制
触发阶段:@EnableAutoConfiguration
-
应用启动时,
@SpringBootApplication
组合了@EnableAutoConfiguration
,触发自动配置流程。 -
AutoConfigurationImportSelector
被调用,负责加载所有候选的自动配置类。
public String[] selectImports(AnnotationMetadata metadata) {// 1. 加载所有候选自动配置类List<String> configurations = getCandidateConfigurations();// 2. 去重、过滤、排序configurations = removeDuplicates(configurations);configurations = filter(configurations, autoConfigurationMetadata);return configurations.toArray(new String[0]);
}
加载与筛选:spring.factories
-
加载所有候选配置类
从所有META-INF/spring.factories
文件中读取EnableAutoConfiguration
对应的配置类。在 Spring Boot 3.x 中,自动配置类的加载方式从 spring.factories 过渡到 AutoConfiguration.imports,并引入了 ImportCandidates 类来处理这一变化。 -
去重与过滤
移除重复的配置类,并通过条件注解(如@ConditionalOnClass
,@ConditionalOnMissingBean
) 有选择的保留当前环境的配置类。-
@ConditionalOnClass:类路径存在指定类时生效
-
@ConditionalOnMissingBean:容器中不存在指定 Bean 时生效
-
@ConditionalOnProperty:配置属性匹配时生效
-
-
排序
根据@AutoConfigureOrder
或@AutoConfigureAfter
调整配置类的加载顺序。
Bean 注册
-
筛选后的自动配置类被解析为标准的
@Configuration
类。 -
每个配置类中的
@Bean
方法根据条件注解动态注册 Bean 到 Spring 容器。
编写自定义Spring Boot Starter
项目结构规划
建议分为两个模块:
-
自动配置模块:包含核心逻辑和自动配置类(如
hello-spring-boot-autoconfigure
)。 -
Starter模块:空项目,仅作为依赖聚合(如
hello-spring-boot-starter
)。
hello-spring-boot-starter-parent(父POM)
├── hello-spring-boot-autoconfigure(自动配置模块)
└── hello-spring-boot-starter(Starter模块)
hello-spring-boot-starter/
├── hello-spring-boot-autoconfigure/
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/com/example/autoconfigure/
│ │ │ │ ├── HelloAutoConfiguration.java
│ │ │ │ ├── HelloProperties.java
│ │ │ │ └── HelloService.java
│ │ │ └── resources/
│ │ │ └── META-INF/
│ │ │ └── spring.factories
│ │ └── test/
│ └── pom.xml
├── hello-spring-boot-starter/
│ └── pom.xml
└── pom.xml
创建自动配置模块(hello-spring-boot-autoconfigure)
添加Maven依赖
<!-- pom.xml -->
<dependencies><!-- Spring Boot 自动配置基础依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId><version>3.1.5</version></dependency><!-- 可选:配置属性处理 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><version>3.1.5</version><optional>true</optional></dependency>
</dependencies>
定义核心服务类
public class HelloService {private String message = "Hello, World!"; // 默认消息public String sayHello() {return message;}// Getter和Setter用于通过配置修改messagepublic String getMessage() { return message; }public void setMessage(String message) { this.message = message; }
}
定义配置属性类(可选)
@ConfigurationProperties(prefix = "hello")
public class HelloProperties {private String message = "Hello, World!";// Getter和Setterpublic String getMessage() { return message; }public void setMessage(String message) { this.message = message; }
}
编写自动配置类
@Configuration
@EnableConfigurationProperties(HelloProperties.class) // 启用配置属性
@ConditionalOnClass(HelloService.class) // 当HelloService在类路径时生效
public class HelloAutoConfiguration {@Bean@ConditionalOnMissingBean // 当用户未自定义HelloService时生效public HelloService helloService(HelloProperties properties) {HelloService service = new HelloService();service.setMessage(properties.getMessage());return service;}
}
注册自动配置
在 resources/META-INF/
下创建 spring.factories
文件:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfigure.HelloAutoConfiguration
创建Starter模块(hello-spring-boot-starter)
添加Maven依赖
<!-- pom.xml -->
<dependencies><!-- 引入自动配置模块 --><dependency><groupId>com.example</groupId><artifactId>hello-spring-boot-autoconfigure</artifactId><version>1.0.0</version></dependency>
</dependencies>
使用自定义Starter
在应用中引入Starter依赖
<!-- 用户项目的pom.xml -->
<dependency><groupId>com.example</groupId><artifactId>hello-spring-boot-starter</artifactId><version>1.0.0</version>
</dependency>
在代码中注入Bean
@RestController
public class HelloController {@Autowiredprivate HelloService helloService;@GetMapping("/hello")public String hello() {return helloService.sayHello();}
}
自定义配置(可选)
在 application.properties
中修改消息:
hello.message=你好, Spring Boot!
相关文章:
Spring之我见 - Spring Boot Starter 自动装配原理
欢迎光临小站:致橡树 Spring Boot Starter 的核心设计理念是 约定优于配置,其核心实现基于 自动配置(Auto-Configuration) 和 条件化注册(Conditional Registration)。以下是其生效原理: 约定…...
LeRobot 项目部署运行逻辑(二)—— Mobile Aloha 真机部署
LeRobot 在开源项目中详细说明了部署流程,所以首先看一下开源的内容,然后再逐步拆解 首先,LeRobot 开源的硬件是配全部在 examples 文件夹中 包括了 Stretch 3、Aloha and Aloha 2 stationary、SO-100、LeKiwi、Moss v1 等机器人 恰好实验…...
大模型面经 | 介绍一下CLIP和BLIP
大家好,我是皮先生!! 今天给大家分享一些关于大模型面试常见的面试题,希望对大家的面试有所帮助。 往期回顾: 大模型面经 | 春招、秋招算法面试常考八股文附答案(RAG专题一) 大模型面经 | 春招、秋招算法面试常考八股文附答案(RAG专题二) 大模型面经 | 春招、秋招算法…...
Java发生OOM是否必然导致JVM退出
Java发生OOM是否必然导致JVM退出? 核心结论 不一定。OOM是否导致JVM退出取决于以下因素: OOM发生的区域JVM启动参数配置是否捕获了OOM异常 详细分析 1. 不同内存区域的OOM影响 内存区域错误类型默认是否导致JVM退出可恢复性Java堆OutOfMemoryError…...
Docker Compose 外部网络(`external: true`)与内部网络的区别
Docker Compose 外部网络(external: true)与内部网络的区别 在 Docker Compose 中,external: true 声明的外部网络与普通(内部)网络有重要区别,以下是它们的详细对比: 1. 定义与创建方式 特性外部网络 (external: true)内部网络 (默认)创建…...
【Android】Wallpaper学习
从wallpaper的设置来了解相关内容: 一,静态壁纸 静态壁纸设置的原理是在WallpaperManagerService里监听/data/system/users/0/wallpaper_orig相关文件的变化来触发设置,通过相应的组件程序去进行绘制, 相应的组件如:…...
Java基础-第一章、基本数据类型
运算符: 1.算术运算符:加减乘除%等 2.逻辑运算符:与或非等 3.关系运算符:大于、小于... 4.赋值运算符: 这里牵扯运算符的运算先后顺序了。 赋值运算的返回值:就是赋值的变量本身...
《Operating System Concepts》阅读笔记:p748-p748
《Operating System Concepts》学习第 64 天,p748-p748 总结,总计 1 页。 一、技术总结 1.Transmission Control Protocol(TCP) 重点是要自己能画出其过程,这里就不赘述了。 二、英语总结(生词:3) transfer, transport, tran…...
Arduino示例代码讲解:Project 08 - Digital Hourglass 数字沙漏
Arduino示例代码讲解:Project 08 - Digital Hourglass 数字沙漏 Project 08 - Digital Hourglass 数字沙漏程序功能概述功能:硬件要求:输出:代码结构全局变量`setup()` 函数`loop()` 函数计时和点亮LED:读取倾斜开关状态:重置LED和计时器:运行过程注意事项Project 08 - …...
报告总结笔记 | Jeff Dean ETH AI趋势 笔记:AI 的重要趋势:我们是如何走到今天的,我们现在能做什么,以及我们如何塑造 AI 的未来?
报告总结笔记 | Jeff Dean ETH AI趋势 笔记:AI 的重要趋势:我们是如何走到今天的,我们现在能做什么,以及我们如何塑造 AI 的未来? 2025年 4 月 14 日,Google Research 及 Google DeepMind 的首席科学家、A…...
RocketMQ实现基于可靠消息的最终一致性
RocketMQ实现基于可靠消息的最终一致性 文章目录 RocketMQ实现基于可靠消息的最终一致性一、RocketMQ应用场景**应用解耦****流量削峰****数据分发** 二、RocketMQ 基础概念1. 核心组件2. 消费模式3. 消息可靠性 三、消息类型按发送方式分同步发送异步发送单向发送 按使用功能特…...
【题解-Acwing】790. 数的三次方根
题目:790. 数的三次方根 题目描述 给定一个浮点数 n,求它的三次方根。 输入 共一行,包含一个浮点数 n 。 输出 共一行,包含一个浮点数,表示问题的解。 注意,结果保留 6 位小数。 数据范围 −10000 ≤ n ≤ 10000 时空限制 1s / 64MB 输入样例 1000.00输出样…...
一键升级OpenSSH/OpenSSL修复安全漏洞
在服务器安全运维过程中,我们经常面临这样的问题:收到高危漏洞通报(如最近的OpenSSH多个CVE漏洞),但Ubuntu系统无法通过apt直接升级到修复版本。这种情况下,传统方法需要手动编译源码,处理依赖关…...
Pycharm 如何删除某个 Python Interpreter
在PyCharm中,点击右下角的“Interpreter Settings”按钮,或者通过菜单栏选择“File” > “Settings”(macOS用户选择“PyCharm” > “Preferences”)。在设置窗口中,导航到“Project: [Your Project Name]” >…...
【C++】深入浅出之多态
目录 多态的概念多态的定义和实现多态的构造条件虚函数虚函数的重写虚函数重写的两个例外协变析构函数作为虚函数重写 C11的override和final重载、重写(覆盖)、隐藏(重定义)的对比相关面试题⭐ 抽象类概念接口继承和实现继承 多态的原理虚函数表多态的原理动态绑定和静态绑定 e…...
精益数据分析(9/126):如何筛选创业路上的关键数据指标
精益数据分析(9/126):如何筛选创业路上的关键数据指标 大家好!在创业的漫漫长路中,数据就像一盏明灯,指引着我们前行的方向。但要让这盏灯发挥作用,关键在于找到那些真正有价值的数据指标。今天…...
【Python爬虫详解】第二篇:HTML结构的基本分析
在上一篇文章中,我们介绍了网络爬虫的基本概念、发展历程和工作原理。要进行有效的网页内容爬取,首先需要理解我们要爬取的对象 —— 网页的基本结构和语法。网页本质上是由HTML代码构成的,爬虫程序需要从HTML中提取我们需要的信息。因此&…...
【C++】 —— 笔试刷题day_21
一、爱丽丝的人偶 题目解析 现在存在n个玩偶,每个玩偶的身高是1、2、3......n; 现在我们要对这些玩偶进行排序(如果x人偶,它左右两边的玩偶一个比x高、一个比x矮,那这个玩偶就会爆炸)。 我们不想要任何一个…...
云点数据读写
一、常见点云数据格式 LAS/LAZ格式 LAS是点云数据的行业标准格式 LAZ是LAS的压缩版本 支持地理参考信息、颜色、强度等属性 PCD格式(Point Cloud Data) PCL(Point Cloud Library)开发的格式 支持ASCII和二进制存储 包含头部信息和数据部分 PLY格式(Polygon File Format…...
Matlab 汽车行驶速度PID控制系统仿真
1、内容简介 Matlab 213-汽车行驶速度PID控制系统仿真 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略...
STM32嵌入式
一、创建工程项目 1、进入软件首页 2、新建项目,【file】->【new project】 3、选择需要的芯片 4、系统内核部分设置 ① 选择晶振(使用外部的高速晶振) ② 选择debug形式(SW类型) 5、时钟设置 6、选择自己需要的引脚设置&a…...
机器学习(神经网络基础篇)——个人理解篇6(概念+代码)
1 在声明一个类中,构建一个属于类的函数,前面为什要加上“self”? 就像下面这一串代码: class TwoLayerNet:def __init__(self, input_size, hidden_size, output_size,weight_init_std0.01):# 初始化权重self.params {}self.p…...
Java学习手册:Filter 和 Listener
在 JavaWeb 开发中,Filter(过滤器)和 Listener(监听器)是两个重要的技术组件,它们在处理客户端请求、管理应用状态和资源以及实现全局逻辑控制等方面发挥着关键作用。 一、Filter(过滤器&#…...
深度学习总结(25)
抽样偏倚问题 非代表性数据有一个特别隐蔽又特别常见的例子,那就是抽样偏倚(sampling bias)。如果你的数据收集过程与你尝试预测的目标之间存在相互影响,就会出现抽样偏倚,从而导致有偏差的结果。 理解数据 将数据…...
探索 Model Context Protocol (MCP):它如何影响 AI 的表现?
Anthropic 公司 Anthropic 是一家技术实力雄厚的公司,也是大模型领域的重要参与者之一。其开发的 **Claude 模型** 是全球首个以编程能力见长并广受欢迎的大语言模型。这款模型凭借卓越的代码生成和理解能力,迅速成为许多开发者工具的核心组件。例如&am…...
Three.js + React 实战系列-3D 个人主页 :完成 Navbar 导航栏组件
在上一节中,我们搭建了项目的基础结构,搭建好了项目框架。 本节我们将继续完善页面结构,完成第一个视觉组件 —— Navbar 导航栏 ✅ 前置准备: ✅下载静态资源在根目录下 (src 同级)谷歌云盘地址 🎥 02 完成 Navba…...
游戏引擎学习第238天:让 OpenGL 使用我们的屏幕坐标
回顾并为今天的内容做准备 我们已经完成了硬件显示的实现,现在通过GPU来显示游戏。原本以为这会花费很长时间,但结果实际所需的时间并不多。因此,我们现在有了进展,但接下来应该做什么还不确定。虽然有很多事情可以做,…...
go+mysql+cocos实现游戏搭建
盲目的学了一段时间了,刚开始从Box2d开始学习,明白了很多,Box2d是物理模型的基础,是我们在游戏中模拟现实的很重要的一个开源工具。后来在朋友的建议下学习了cocos,也是小程序开发的利器,而golang是一款高效…...
Linux 网络基础(二) (传输协议层:UDP、TCP)
目录 一、传输层的意义 二、端口号 1、五元组标识一个通信 2、端口号范围划分 3、知名端口号(Well-Know Port Number) (1)查看端口号 4、绑定端口号数目问题 5、pidof & netstat 命令 (1)ne…...
Vue常用指令入门
1. v-for 作用:用于遍历对象或数组 注意:需要提供key属性,可以提高性能和避免渲染错误,值通常为index或item.id <li v-for"(item, index) in items" :key"index">{{ item }} </li>2. v-if,v-el…...
【文献阅读】EndoNet A Deep Architecture for Recognition Tasks on Laparoscopic Videos
关于数据集的整理 Cholec80 胆囊切除手术视频数据集介绍 https://zhuanlan.zhihu.com/p/700024359 数据集信息 Cholec80 数据集 是一个针对内窥镜引导 下的胆囊切除手术视频流程识别数据集。数据集提供了每段视频中总共7种手术动作及总共7种手术工具的标注,标…...
UML统一建模
UML UML(统一建模语言)介绍 UML(统一建模语言)介绍 面向对象软件开发需要经过OOA面向对象分析、OOD面向对象设计和OOP面向对象编程三个阶段。OOA对目标系统进行分析并寄哪里分析模型,并将之文档化,OOD用面向…...
Ubuntu下安装和卸载MySQL
Ubuntu下安装和卸载MySQL 下面的演示系统版本:Ubuntu 24.04 更新系统软件包 在开始安装之前,建议先更新系统的软件包列表,以确保所有依赖项是最新的。 sudo apt update && sudo apt upgrade -y安装MySQL服务器 Ubuntu的官方软件…...
物联网技术赋能:复杂环境下的能源数据零丢失
安科瑞顾强 在全球能源挑战日益严峻的背景下,高效节能已成为各行业的核心诉求。无论是商业综合体、工业厂房还是公共设施,如何实现能源的精细化管理成为关键课题。安科瑞能耗云平台凭借其创新技术与多功能服务,为企业提供了一站式能源管理解…...
卷积神经网络综述
摘要 本文对卷积神经网络(Convolutional Neural Network,CNN)进行了全面综述。首先介绍了卷积神经网络的发展历程,包括早期的理论基础和关键突破。接着详细阐述了卷积神经网络的结构组成,包括卷积层、池化层、全连接层…...
SpringBoot3设置maven package直接打包成二进制可执行文件
注意事项 SpringBoot普通native打包顺序clean compile spring-boot:process-aot native:compile 使用以下配置只会的打包顺序clean package(注意:使用此配置以后打包会有编译后的class文件、jar包、original源文件、二进制可执行文件【Linux是无后缀的包…...
在 Anaconda 上安装多版本 Python 解释器并在 PyCharm 中配置
默认已安装好 Anaconda 和 PyCharm ,想在 Anaconda 上安装最新版本的 Python 解释器。 一、在 Anaconda 上创建虚拟环境 在连网状态下进入系统的命令提示符(快捷键:win r ,输入 cmd 即可),输入如下命令&a…...
AES (高级加密标准)
原理详解 AES是一种对称加密算法,使用相同的密钥进行加密和解密。它采用替代-置换网络(SPN)结构,主要步骤包括: 密钥扩展:从初始密钥派生多轮密钥 初始轮:AddRoundKey(轮密钥加) 主轮ÿ…...
Git拉分支技巧:从零开始创建并推送分支
Git拉分支技巧:从零开始创建并推送分支 在团队协作开发中,Git 分支管理是不可或缺的技能。合理地创建、同步和推送分支,不仅能提高开发效率,还能避免代码冲突。本文将基于以下技巧,详细讲解如何从零开始创建并推送一个…...
线性回归之归一化(normalization)
文章目录 归一化与梯度下降归一化的必要性:从特征量纲到梯度下降问题背景矛盾与低效归一化的作用 归一化提高模型精度的原因归一化的本质常见归一化方法最大值最小值归一化示例说明优缺点分析 标准归一化具体机制示例说明 强调 归一化与梯度下降 归一化与梯度下降 &…...
mac监控linux上mysql性能(Grafana+Prometheus+mysqld_exporter)
一、监控查看端安装 Grafana安装-CSDN博客 普罗米修斯Prometheus监控安装(mac)-CSDN博客 1.启动Grafana服务 brew services start grafana 打开浏览器输入http://localhost:3000进入grafana登录页面 (默认用户名和密码都为admin,进入后…...
【玩泰山派】MISC(杂项)- linux桌面环境
文章目录 linux桌面环境linux四大桌面环境概述ubuntu基于四大桌面环境的版本 显示管理器gdm3(GNOME Display Manager)lightdm(Lightweight Display Manager)SDDM(Simple Desktop Display Manager)KDM&#…...
MVCC介绍
MVCC(多版本并发控制)详解 MVCC(Multi-Version Concurrency Control) 是一种数据库并发控制技术,核心思想是通过维护数据的多个版本来实现读写操作的无锁并发,从而在高并发场景下提升性能。它广泛用于 MyS…...
神经网络与模型训练过程笔记
1.专有名词 ANN 人工神经网络,一种受生物神经元启发的监督学习算法。输入数据通过网络中的层级函数传递,激活特定神经元。函数复杂度越高,模型对数据的拟合能力越强,预测精度越高。 偏置项 其中x下表从1开始的是输入变量…...
ASP.NET 0~1学习
变量 string username Request["id"]; 声明并初始化一个字符串变量 username 数据类型 下面列出了常用的数据类型: 类型描述实例int整数(全数字)103, 12, 5168float浮点数3.14, 3.4e38decimal十进制数字(高精度&a…...
optool为macho文件增加动态库
对macho文件有一定理解后,了解下optool是如何给macho文件增加动态库等功能的 optool 源码 环境 macOS 13.4 (22F66) Xcode 14.3.1 0x0 编译 下载源码 $ git clone --recurse-submodules https://github.com/alexzielenski/optool.git修改下Deployment Target,比如改成11.0&…...
【C++】类和对象之日期类的实现(构造、运算符重载)
文章目录 一、日期类要实现的函数二、函数实现1、GetMonthDay获取对应月份的天数2、CheckDate检查日期3、Date构造函数4、Print打印日期5、运算符重载1. 、、-、-2. 前置/--、后置/--3. 两个日期类相减(求相差日期) 6、比较7、流插入、流提取࿰…...
【Rust 精进之路之第9篇-所有权·核心】规则与移动 (Move):Rust 内存安全基石详解
系列: Rust 精进之路:构建可靠、高效软件的底层逻辑 作者: 码觉客 发布日期: 2025年4月20日 引言:没有 GC,Rust 如何管好内存?答案是所有权! 在我们的 Rust 探索之旅中,我们已经学习了变量、数据类型、控制流、函数和强大的构建工具 Cargo。现在,我们将踏入 Rust 最…...
【任务调度】xxl-job入门
xxl- job 入门 附上笔者写的测视示例:chenmeng-test-demos/demo8-task/task-xxl-job at master cmty256/chenmeng-test-demos 官方文档 XXL-JOB官网 源码仓库地址: Github:https://github.com/xuxueli/xxl-job Gitee:http://g…...
Go语言--语法基础4--基本数据类型--浮点数类型
3 、浮点数类型 浮点型用于表示包含小数点的数据,比如 1.234 就是一个浮点型数据。 Go 语言中的浮点类型采用 IEEE-754 标准的表达方式。 float32 精度是小数点后 7 位 float64 精度是小数点后 15 位。 1. 浮点数表示 Go 语言定义了两个类型 float32 和 floa…...