Spring之我见 - Spring Boot Starter 自动装配原理

 欢迎光临小站:致橡树

Spring Boot Starter 的核心设计理念是 约定优于配置,其核心实现基于 自动配置(Auto-Configuration)条件化注册(Conditional Registration)。以下是其生效原理:

约定大于配置

通过预定义合理的默认行为和规范,减少开发者需要手动配置的步骤。比较显著的变化就是减少XML配置。还有一些实际体现如下所示:

  • 项目结构约定

    • 默认目录结构:如 src/main/java 存放代码,src/main/resources 存放配置文件。

    • 配置文件命名application.propertiesapplication.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

项目结构规划

建议分为两个模块:

  1. 自动配置模块:包含核心逻辑和自动配置类(如 hello-spring-boot-autoconfigure)。

  2. 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!

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

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

相关文章

精益数据分析(7/126):打破创业幻想,拥抱数据驱动

精益数据分析&#xff08;7/126&#xff09;&#xff1a;打破创业幻想&#xff0c;拥抱数据驱动 在创业的道路上&#xff0c;我们都怀揣着梦想&#xff0c;但往往容易陷入自我编织的幻想中。我希望通过和大家一起学习《精益数据分析》&#xff0c;能帮助我们更清醒地认识创业过…

牛客java练习题

[toc] 1.依赖注入 依赖注入是一种设计模式和编程思想,不依赖 具体的框架实现,可以通过多种方式和框架来实现可以通过Spring , Google Guice , PicoContainer 等都可以实现依赖注入,也可以通过手动编写实现目的: 为了解耦合,将对象之间的依赖关系从代码中解耦出来, 使系统更加…

大模型应用开发自学笔记

理论学习地址&#xff1a; https://zh.d2l.ai/chapter_linear-networks/index.html autodl学术加速&#xff1a; source /etc/network_turboconda常见操作: 删除&#xff1a; conda remove --name myenv --all -y导出&#xff1a; conda env export > environment.yml…

鸿蒙ArkUI实战之TextArea组件、RichEditor组件、RichText组件、Search组件的使用

本文接上篇继续更新ArkUI中组件的使用&#xff0c;本文介绍的组件有TextArea组件、RichEditor组件、RichText组件、Search组件&#xff0c;这几个组件的使用对应特定场景&#xff0c;使用时更加需要注意根据需求去使用 TextArea组件 官方文档&#xff1a; TextArea-文本与输…

除了`String`、`StringBuffer` 和 `StringBuilder`之外,还有什么处理字符串的方法?

一、标准库中的字符串处理类 1. StringJoiner&#xff08;Java 8&#xff09; 用途&#xff1a;用于在拼接字符串时自动添加分隔符、前缀和后缀。示例&#xff1a;StringJoiner sj new StringJoiner(", ", "[", "]"); sj.add("A").…

Qt中读写结构体字节数据

在Qt中读写结构体字节数据通常涉及将结构体转换为字节数组(QByteArray)或直接从内存中读写。以下是几种常见方法&#xff1a; 方法1&#xff1a;使用QDataStream读写结构体 cpp #include <QFile> #include <QDataStream>// 定义结构体 #pragma pack(push, 1) //…

Windows 10 上安装 Spring Boot CLI详细步骤

在 Windows 10 上安装 Spring Boot CLI 可以通过以下几种方式完成。以下是详细的步骤说明&#xff1a; 1. 手动安装&#xff08;推荐&#xff09; 步骤 1&#xff1a;下载 Spring Boot CLI 访问 Spring Boot CLI 官方发布页面。下载最新版本的 .zip 文件&#xff08;例如 sp…

Unity3D仿星露谷物语开发37之浇水动画

1、目标 当点击水壶时&#xff0c;实现浇水的动画。同时有一个水从水壶中流出来的特效。 假如某个grid被浇过了&#xff0c;则不能再浇水了。。 如果某个grid没有被dug过&#xff0c;也不能被浇水。 2、优化Settings.cs脚本 增加如下内容&#xff1a; public static float…

【2】Kubernetes 架构总览

Kubernetes 架构总览 主节点与工作节点 主节点 Kubernetes 的主节点&#xff08;Master&#xff09;是组成集群控制平面的关键部分&#xff0c;负责整个集群的调度、状态管理和决策。控制平面由多个核心组件构成&#xff0c;包括&#xff1a; kube-apiserver&#xff1a;集…

如何对docker镜像存在的gosu安全漏洞进行修复——筑梦之路

这里以mysql的官方镜像为例进行说明&#xff0c;主要流程为&#xff1a; 1. 分析镜像存在的安全漏洞具体是什么 2. 根据分析结果有针对性地进行修复处理 3. 基于当前镜像进行修复安全漏洞并复核验证 # 镜像地址mysql:8.0.42 安全漏洞现状分析 dockerhub网站上获取该镜像的…

【Tauri2】026——Tauri+Webassembly

前言 不多废话 直言的说&#xff0c;笔者看到这篇文章大佬的文章 【04】Tauri 入门篇 - 集成 WebAssembly - 知乎https://zhuanlan.zhihu.com/p/533025312尝试集成一下WebAssembly&#xff0c;直接开始 正文 准备工作 新建一个项目 安装 vite的rsw插件和rsw pnpm instal…

OpenHarmony Camera开发指导(五):相机预览功能(ArkTS)

预览是在相机启动后实时显示场景画面&#xff0c;通常在拍照和录像前执行。 开发步骤 创建预览Surface 如果想在屏幕上显示预览画面&#xff0c;一般由XComponent组件为预览流提供Surface&#xff08;通过XComponent的getXcomponentSurfaceId方法获取surfaceid&#xff09;&…

puzzle(0531)脑力航迹

目录 脑力航迹 规则 解法 简单模式 中等模式 困难模式 专家模式 脑力航迹 规则 2条航迹会产生一个相对航迹&#xff1a; 根据相对航迹和其中一个航迹推导另外一个航迹。 解法 没有任何需要推理的地方&#xff0c;就是纯粹的2个矢量相加。 简单模式 中等模式 困难模…

在win上安装Ubuntu安装Anaconda(linx环境)

一&#xff0c;安装Ubuntu 1. 在 Microsoft 商城去下载Ubuntu(LTS:是长期维护的版本) 2.安装完之后启动程序&#xff0c;再重新打开一个黑窗口&#xff1a; wsl --list --verbose 3.关闭Ubuntu wsl --shutdown Ubuntu-22.04 WSL2 Ubuntu-20.04文件太占c盘空间&#xff0c;…

NEAT 算法解决 Lunar Lander 问题:从理论到实践

NEAT 算法解决 Lunar Lander 问题:从理论到实践 0. 前言1. 定义环境2. 配置 NEAT3. 解决 Lunar lander 问题小结系列链接0. 前言 在使用 NEAT 解决强化学习问题一节所用的方法只适用于较简单的强化学习 (reinforcement learning, RL) 环境。在更复杂的环境中使用同样的进化解…

【KWDB 创作者计划】_上位机知识篇---ESP32-S3Arduino

文章目录 前言1. ESP32-S3核心特性2. 开发环境搭建(1) 安装Arduino IDE(2) 添加ESP32-S3支持(3) 选择开发板(4) 关键配置3. 基础代码示例(1) 串口通信(USB/硬件串口)(2) Wi-Fi连接(3) 蓝牙LE广播4. 高级功能开发(1) USB OTG功能(2) AI加速(MicroTensorFlow)(3) 双核任务处理…

JavaScript学习教程,从入门到精通,DOM节点操作语法知识点及案例详解(21)

DOM节点操作语法知识点及案例详解 一、语法知识点 1. 获取节点 // 通过ID获取 const element document.getElementById(idName);// 通过类名获取&#xff08;返回HTMLCollection&#xff09; const elements document.getElementsByClassName(className);// 通过标签名获取…

PCA 降维实战:从原理到电信客户流失数据应用

一、简介 在机器学习领域&#xff0c;数据的特征维度往往较高&#xff0c;这不仅会增加计算的复杂度&#xff0c;还可能导致过拟合等问题。主成分分析&#xff08;Principal Component Analysis&#xff0c;简称 PCA&#xff09;作为一种经典的降维技术&#xff0c;能够在保留数…

信创时代编程开发语言选择指南:国产替代背景下的技术路径与实践建议

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、CSDN平台优质创作者&#xff0c;高级开发工程师&#xff0c;数学专业&#xff0c;10年以上C/C, C#, Java等多种编程语言开发经验&#xff0c;拥有高级工程师证书&#xff1b;擅长C/C、C#等开发语言&#xff0c;熟悉Java常用开…

Arcgis10.1的汉化包及破解文件分享

Arcgis10.1的汉化包分享 网上有好多10.2的汉化包&#xff0c;但是10.1的汉化包很少&#xff0c;特在此分析出来给大家 Arcgis10.1破解文件及汉化包: (访问密码: 9784) license manager破解安装文件 另外也分享了license manager破解安装文件&#xff0c;也在相同的分享链接里…