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)。以下是其生效原理: 约定…...
如何高效利用呼叫中心系统和AI语音机器人
要更好地使用呼叫中心系统和语音机器人,需要结合两者的优势,实现自动化、智能化、高效率的客户服务与业务运营。以下是优化策略和具体实践方法: 一、呼叫中心系统优化 1. 智能路由与IVR优化 智能ACD(自动呼叫分配) …...
【Windows上配置Git环境】
在Windows上配置Git环境可以按照以下步骤进行: 1. 下载Git 打开浏览器,访问Git官方网站https://git-scm.com/downloads。在下载页面中,找到适用于Windows的下载链接,根据你的系统是32位还是64位选择相应的安装包进行下载 。 2.…...
OpenCV基础01-图像文件的读取与保存
介绍: OpenCV是 Open Souce C omputer V sion Library的简称。要使用OpenCV需要安装OpenCV包,使用前需要导入OpenCV模块 安装 命令 pip install opencv-python 导入 模块 import cv2 1. 图像的读取 import cv2 img cv2.imread(path, flag)这里的flag 是可选参数&…...
C 语言的未来:在变革中坚守与前行
C 语言,作为编程语言领域的一位 “老将”,自诞生以来就一直扮演着至关重要的角色。历经数十年的发展,它的影响力依然广泛而深远。在科技飞速发展的今天,新的编程语言如雨后春笋般不断涌现,C 语言的未来发展走向成为了众…...
go语言优雅关机和优雅重启笔记
一、优雅关机 生活化例子 餐馆关门:你去餐馆吃火锅,刚坐下点完菜(客户端发请求),餐馆老板突然接到通知要停电(收到关机指令)。老板很贴心,先停止接待新客人(停止接收新请…...
【算法】计数排序、桶排序、基数排序
算法系列八:非比较排序 一、计数排序 1.实现 1.1步骤 1.2代码 2.性质 2.1稳定性 2.1.1从前往后前始版: 2.1.2从后往前末始版: 2.2复杂度 2.2.1时间复杂度 2.2.2空间复杂度 二、桶排序 1.实现 1.1步骤 1.2代码 2.稳定性 三、…...
Halcon应用:相机标定
提示:若没有查找的算子,可以评论区留言,会尽快更新 Halcon应用:相机标定 前言一、Halcon应用?二、应用实战1、图像理解1.1、开始标定 前言 本篇博文主要用于记录学习Halcon中算子的应用场景,及其使用代码和…...
【C++ 程序设计】实战:C++ 实践练习题(31~40)
目录 31. 数列:s 1 + 2 + 3 + … + n 32. 数列:s 1 - 2 - 3 - … - n 33. 数列:s 1 + 2 - 3 + … - n 34. 数列:s 1 - 2 + 3 - … &#…...
【perf】perf工具的使用生成火焰图
文章目录 1. What is perf?2. perf使用2.1 perf的子工具集2.2 常用指令perf list指令格式参数perf中事件分类使用示例 perf stat指令格式参数 perf top指令格式参数交互式界面操作使用示例 perf record指令格式参数使用示例 perf report指令格式参数交互式界面操作使用示例 pe…...
绿幕抠图直播软件-蓝松抠图插件--使用相机直播,灯光需要怎么打?
使用SONY相机进行绿幕抠图直播时,灯光布置是关键,直接影响抠图效果和直播画质。以下是详细的灯光方案和注意事项: 一、绿幕灯光布置核心原则 均匀照明:绿幕表面光线需均匀,避免阴影和反光(亮度差控制在0.5…...
从外网访问局域网服务器的方法
一、为什么局域网的服务器无法在外网访问? 服务器、电脑之间靠IP地址寻址,目前大部分基于IPV4进行寻址访问。但是因为IPV4的地址数量有限,中国分到的还比较少,所以非常紧缺。 一个解决方案就是在局域网来建立一个内部的网…...
每日面试实录·携程·社招·JAVA
📍面试公司:携程 👜面试岗位:后端开发工程师(社招) 🕐面试时长:约 50 分钟 🔄面试轮次:第 1 轮技术面 ✨面试整体节奏: 这场携程的社招 Java 一面…...
Redis增删改查
### 进入redis控制台 redis-cli --raw #加上raw,防止中文乱码### 增 127.0.0.1:6379> LPUSH list0 "hello" #增加一个list 1 127.0.0.1:6379> LRANGE list0 0 -1 #查看list hello### 删 127.0.0.1:6379> DEL list0 #删除list 1 127.0.0.1:6379> LRANG…...
机器学习 Day12 集成学习简单介绍
1.集成学习概述 1.1. 什么是集成学习 集成学习是一种通过组合多个模型来提高预测性能的机器学习方法。它类似于: 超级个体 vs 弱者联盟 单个复杂模型(如9次多项式函数)可能能力过强但容易过拟合 组合多个简单模型(如一堆1次函数)可以增强能力而不易过拟合 集成…...
学习笔记十九——Rust多态
🧩 Rust 多态终极通俗指南 📚 目录导航 多态一句话概念静态分派 vs 动态分派——根本差异参数化多态(泛型) 3.1 函数里的泛型 3.2 结构体里的泛型 3.3 方法里的泛型 3.4 枚举里的泛型Ad hoc 多态(特例多态࿰…...
交换机与路由器的主要区别:深入分析其工作原理与应用场景
在现代网络架构中,交换机和路由器是两种至关重要的设备。它们在网络中扮演着不同的角色,但很多人对它们的工作原理和功能特性并不十分清楚。本文将深入分析交换机与路由器的主要区别,并探讨它们的工作原理和应用场景。 一、基本定义 1. 交换…...
【Oracle专栏】Oracle中的虚拟列
Oracle相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 1.背景 在EXP方式导出时,发现 出现如下提示 EXP-00107: virtual column 不支持,因此采用expdp方式导出。于是本文针对oracle虚拟列进行简单介绍。 2. 相…...
2020 年 7 月大学英语四级考试真题(组合卷)——解析版
🏠个人主页:fo安方的博客✨ 💂个人简历:大家好,我是fo安方,目前中南大学MBA在读,也考取过HCIE Cloud Computing、CCIE Security、PMP、CISP、RHCE、CCNP RS、PEST 3等证书。🐳 &…...
大语言模型的训练、微调及压缩技术
The rock can talk — not interesting. The rock can read — that’s interesting. (石头能说话,不稀奇。稀奇的是石头能读懂。) ----硅谷知名创业孵化器 YC 的总裁 Gar Tan 目录 1. 什么是大语言模型? 2. 语言建模ÿ…...
NEAT 算法解决 Lunar Lander 问题:从理论到实践
NEAT 算法解决 Lunar Lander 问题:从理论到实践 0. 前言1. 定义环境2. 配置 NEAT3. 解决 Lunar lander 问题小结系列链接0. 前言 在使用 NEAT 解决强化学习问题一节所用的方法只适用于较简单的强化学习 (reinforcement learning, RL) 环境。在更复杂的环境中使用同样的进化解…...
firewall指令
大家好,今天我们继续来了解服务管理,来看看打开或关闭指定端口,那么话不多说,开始吧. 1.打开或者关闭指定端口 在真正的生产环境,往往需要防火墙,但问题来了,如果我们把防火墙打开,那么外部请求数据包就不能跟服务器监听通讯,这时,需要打开指定的端口,比如80,22,8080等. 2.fi…...
【MySQL】MySQL表的增删改查(CRUD) —— 上篇
目录 MySQL表的增删改查(CRUD) 1. 新增(Create)/插入数据 1.1 单行数据 全列插入 insert into 表名 values(值, 值......); 1.2 单行数据 指定列插入 1.3 多行数据 指定列插入 1.4 关于时间日期(datetime&am…...
STM32的三种启动方式
目录 一、从主闪存存储器启动(Main Flash Memory) 二、从系统存储器启动(System Memory) 三、从内置SRAM启动(Embedded SRAM) 一、从主闪存存储器启动(Main Flash Memory) >&g…...
软考高级系统架构设计师-第15章 知识产权与标准化
【本章学习建议】 根据考试大纲,本章主要考查系统架构设计师单选题,预计考3分左右,较为简单。 15.1 标准化基础知识 1. 标准的分类 分类 内容 国际标准(IS) 国际标准化组织(ISO)、国际电工…...
Spring Boot 整合 DeepSeek 实现AI对话 (保姆及教程)
文章目录 文章目录 前言 一、创建 spring boot 工程 二、申请key 三、修改配置文件 application.properties 四、编写控制器(controller) 五、运行调试 前言 提示:随着人工智能的不断发展,ai这门技术也越来越重要,很多…...
Java File 类详解
Java File 类详解 File 类是 Java 中用于表示文件和目录路径名的抽象类,位于 java.io 包中。它提供了丰富的 API,用于操作文件系统,包括创建、删除、重命名、查询文件属性等功能。 1. File 类核心知识点 (1)构造方法…...
通过特定协议拉起 electron 应用
在 Android 通过 sheme 协议可以拉起其他应用。 electron 应用也可以通过类似特定协议被拉起。 在同时有 web、客户端的应用里,可以通过这种方式在 web 拉起客户端。 支持拉起客户端 const PROTOCOL xxxif (process.defaultApp) {// 这里是开发环境,有…...
前端与传统接口的桥梁:JSONP解决方案
1.JSONP原理 1.1.动态脚本注入 说明:通过创建 <script> 标签绕过浏览器同源策略 1.2.回调约定 说明:服务端返回 函数名(JSON数据) 格式的JS代码 1.3.自动执行 说明:浏览器加载脚本后立即触发前端预定义的回调函数(现代开…...
Vue3中provide和inject数据修改规则
在 Vue3 中,通过 inject 接收到的数据是否可以直接修改,取决于 provide 提供的值的类型和响应式处理方式: 1. 若提供的是普通值(非响应式数据) javascript 复制 // 父组件 provide(staticValue, 123); 子组件修改行…...
