文章目录

  • 1. Spring Boot Starter 的本质
  • 2. Starter 的模块结构(推荐)
  • 3. 制作 `xxx-spring-boot-autoconfigure` 模块
    • 3.1 添加必要的依赖
    • 3.2 编写具体功能的配置类
    • 3.3 编写自动化配置类 (`@AutoConfiguration`)
    • 3.4 注册自动化配置类 (`.imports` 或 `spring.factories`)
  • 4. 制作 `xxx-spring-boot-starter` 模块
  • 5. 使用你的 Starter 依赖
  • 6. 最佳实践和注意事项
  • 总结

在企业级应用开发中,我们经常会遇到一些通用的功能模块,比如统一的日志处理、RPC 调用客户端、特定的安全认证逻辑等如果每个项目都重复编写这些配置和代码,效率低下且容易出错

Spring Boot Starter 的出现,正是为了解决这个问题。Starter 是一种特殊的 Maven 或 Gradle 依赖,它能够将相关的依赖和自动化配置打包在一起,让其他项目只需要简单地引入一个 Starter 依赖,就能自动获得所需的功能,无需手动配置

本文将基于 Spring Boot 的自动化装配原理,手把手教你如何制作自己的 Spring Boot Starter 依赖

1. Spring Boot Starter 的本质

Spring Boot Starter 的本质是一个依赖聚合器自动化配置提供者

  • 依赖聚合: 一个 Starter 通常会引入实现某个功能所需的所有其他依赖例如,spring-boot-starter-web 会引入 Spring MVC、Tomcat 等依赖
  • 自动化配置: Starter 中包含了自动化配置类,这些类会根据当前项目的环境(依赖、配置等)自动配置相关的 Bean,使得用户无需手动编写繁琐的配置

制作自己的 Starter,就是将你的通用功能封装在一个或多个模块中,并按照 Spring Boot 的规范提供自动化配置


2. Starter 的模块结构(推荐)

为了清晰起见,通常会将一个 Starter 分为两个模块:

  • xxx-spring-boot-starter: 这是提供给用户引入的模块它本身不包含实际的代码,只作为依赖的入口,主要依赖于 xxx-spring-boot-autoconfigure 模块
  • xxx-spring-boot-autoconfigure: 这是包含实际自动化配置逻辑的模块你所有的配置类、条件注解、以及 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件都放在这个模块中

这种分离的好处是:

  • 职责分离: Starter 模块只负责依赖管理,autoconfigure 模块负责自动化配置逻辑
  • 清晰: 用户引入 Starter 模块即可,无需关心内部实现

当然,对于简单的 Starter,你也可以将所有内容放在一个模块中,但这不符合最佳实践


3. 制作 xxx-spring-boot-autoconfigure 模块

这是实现自动化配置的核心模块

3.1 添加必要的依赖

首先,在 xxx-spring-boot-autoconfigure 模块的 pom.xml (Maven) 或 build.gradle (Gradle) 中添加 Spring Boot 的自动化配置依赖:

Maven:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 如果你的自动化配置依赖于某个第三方库,也需要在这里添加 -->
<!-- <dependency><groupId>com.example</groupId><artifactId>some-library</artifactId>
</dependency> -->

Gradle:

implementation 'org.springframework.boot:spring-boot-autoconfigure'
// 如果你的自动化配置依赖于某个第三方库,也需要在这里添加
// implementation 'com.example:some-library'

spring-boot-autoconfigure 模块包含了 @ConditionalOn... 等条件注解,以及 Spring Boot 自动化配置所需的基础设施

3.2 编写具体功能的配置类

创建包含你通用功能具体 Bean 定义的配置类这些类通常使用 @Configuration@Bean 注解

// src/main/java/com/example/starter/autoconfigure/MyServiceConfig.java
@Configuration
public class MyServiceConfig {// 定义一个通用的服务 Bean@Beanpublic MyService myService() {return new MyService();}// 如果你的服务需要配置属性,可以使用 @ConfigurationProperties@Bean@ConfigurationProperties(prefix = "my.service")public MyServiceProperties myServiceProperties() {return new MyServiceProperties();}
}

3.3 编写自动化配置类 (@AutoConfiguration)

创建标记为 @AutoConfiguration 的自动化配置类这个类将作为自动化配置的入口,并使用相应的条件注解来控制何时生效

// src/main/java/com/example/starter/autoconfigure/MyServiceAutoConfiguration.java
@AutoConfiguration // 标记为自动化配置类 (Spring Boot 2.7+)
// @Configuration // 兼容早期版本,但推荐使用 @AutoConfiguration
@ConditionalOnClass(MyService.class) // 条件:只有当 MyService.class 存在时才生效
@EnableConfigurationProperties(MyServiceProperties.class) // 启用配置属性绑定
@Import(MyServiceConfig.class) // 导入包含具体 Bean 定义的配置类
public class MyServiceAutoConfiguration {// 这个类本身可以不定义 Bean,主要通过 @Import 导入其他配置类// 也可以在这里直接定义 Bean,并使用条件注解// @Bean// @ConditionalOnMissingBean // 如果没有 MyService 的 Bean,则创建默认的// public MyService defaultMyService() {//     return new MyService();// }
}

重要提示:

  • 使用 @AutoConfiguration 注解(Spring Boot 2.7+)
  • 使用 @ConditionalOnClass 等条件注解来控制自动化配置的生效条件通常会判断某个核心类是否存在,或者某个配置属性是否设置
  • 使用 @Import 注解导入包含具体 Bean 定义的配置类
  • 如果你的功能需要配置属性,使用 @EnableConfigurationProperties@ConfigurationProperties 来绑定属性

3.4 注册自动化配置类 (.importsspring.factories)

这是最关键的一步,让 Spring Boot 能够找到你的自动化配置类

推荐方式 (Spring Boot 2.7+):

xxx-spring-boot-autoconfigure 模块的 src/main/resources/META-INF/spring/ 目录下创建 org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件

在该文件中,每行填写一个你的自动化配置类的全限定名

# src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.starter.autoconfigure.MyServiceAutoConfiguration

兼容早期版本方式:

xxx-spring-boot-autoconfigure 模块的 src/main/resources/META-INF/ 目录下创建 spring.factories 文件

在该文件中,添加如下内容:

# src/main/resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.starter.autoconfigure.MyServiceAutoConfiguration

在 Spring Boot 2.7+ 中,你可以同时使用这两种方式,但推荐优先使用 .imports 文件


4. 制作 xxx-spring-boot-starter 模块

这个模块非常简单,它的主要作用就是依赖 xxx-spring-boot-autoconfigure 模块,并遵循 Starter 的命名规范

xxx-spring-boot-starter 模块的 pom.xml (Maven) 或 build.gradle (Gradle) 中添加依赖:

Maven:

<dependency><groupId>com.example</groupId><artifactId>my-service-spring-boot-autoconfigure</artifactId><version>1.0.0-SNAPSHOT</version>
</dependency>

Gradle:

implementation 'com.example:my-service-spring-boot-autoconfigure:1.0.0-SNAPSHOT'

这个模块通常不需要编写任何 Java 代码


5. 使用你的 Starter 依赖

现在,其他 Spring Boot 项目只需要在 pom.xmlbuild.gradle 中引入你的 Starter 依赖即可:

Maven:

<dependency><groupId>com.example</groupId><artifactId>my-service-spring-boot-starter</artifactId><version>1.0.0-SNAPSHOT</version>
</dependency>

Gradle:

implementation 'com.example:my-service-spring-boot-starter:1.0.0-SNAPSHOT'

当用户引入这个依赖后,你的 xxx-spring-boot-autoconfigure 模块就会被添加到项目的运行时类路径中。Spring Boot 启动时,AutoConfigurationImportSelector 会找到并加载 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件(或 spring.factories),发现并处理你的 MyServiceAutoConfiguration如果条件满足,MyServiceAutoConfiguration 中导入的 MyServiceConfig 生效,MyService Bean 就会被自动创建并注册到 Spring 容器中

用户可以直接在他们的代码中注入并使用 MyService

@Service
public class SomeBusinessLogic {@Autowiredprivate MyService myService; // 直接注入,无需手动配置// ... 使用 myService
}

6. 最佳实践和注意事项

  • 命名规范: 遵循 Spring Boot Starter 的命名规范 xxx-spring-boot-starter
  • 版本管理: 合理管理你的 Starter 版本
  • 文档: 为你的 Starter 提供清晰的文档,说明它的功能、如何使用、支持哪些配置属性等
  • 条件注解: 充分利用条件注解,确保你的自动化配置只在需要时生效,避免不必要的 Bean 创建和冲突
  • 配置属性: 如果你的功能需要用户进行配置,使用 @ConfigurationProperties 提供类型安全的配置
  • 日志: 在自动化配置类中使用日志,方便用户排查问题
  • 测试: 编写自动化测试来验证你的 Starter 是否按预期工作

总结

制作自己的 Spring Boot Starter 依赖,是提升代码复用性和开发效率的有效手段通过理解 Spring Boot 的自动化装配原理,特别是 META-INF/spring.factories.imports 文件以及条件注解的作用,你就能轻松地将你的通用功能封装成易于使用的 Starter,让其他项目能够享受到自动化装配带来的便利

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

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

相关文章

Qt6之qml自定义控件开发流程指南

Qt6之qml自定义控件开发流程指南 &#x1f6e0;️ 一、基础控件创建 定义 QML 文件 在工程中新建 QML 文件&#xff08;如 CustomButton.qml&#xff09;&#xff0c;文件名首字母大写。 使用基础组件&#xff08;如 Rectangle、Text&#xff09;构建控件逻辑&#xff0c;通过…

Vue简介,什么是Vue(Vue3)?

什么是Vue&#xff1f; Vue是一款用于构建用户界面的JavaScript框架。 它基于标准HTML、CSS和JavaScript构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用户界面。无论是简单的还是复杂地界面&#xff0c;Vue都可以胜任。 声明式渲染…

从零开始构建Airbyte数据管道:PostgreSQL到BigQuery实战指南

作为数据工程师&#xff0c;ETL&#xff08;Extract, Transform, Load&#xff09;流程是日常工作的核心。然而&#xff0c;构建和维护数据管道往往耗时且复杂。幸运的是&#xff0c;开源工具Airbyte提供了一种更便捷的解决方案——它支持350预构建连接器&#xff0c;允许通过无…

JavaScript的初步学习

目录 JavaScript简介 主要特点 主要用途 JavaScript的基本特性 JavaScript的引入方式 1. 内联方式 (Inline JavaScript) 2. 内部方式 (Internal JavaScript / Embedded JavaScript) 3. 外部方式 (External JavaScript) JavaScript的语法介绍 1.书写语法 2.输出语句 3.…

洛谷P1379 八数码难题【A-star】

P1379 八数码难题 八数码难题首先要进行有解性判定&#xff0c;避免无解情况下盲目搜索浪费时间。 有解性判定 P10454 奇数码问题 题意简述 在一个 n n n \times n nn 的网格中进行&#xff0c;其中 n n n 为奇数&#xff0c; 1 1 1 个空格和 [ 1 , n 2 − 1 ] [1,n^2…

MySQL Buffer Pool 深度解析:从架构设计到性能优化(附详细结构图解)

在 MySQL 数据库的世界里&#xff0c;有一个决定性能上限的"神秘仓库"——Buffer Pool。它就像超市的货架&#xff0c;把最常用的商品&#xff08;数据&#xff09;放在最方便拿取的地方&#xff0c;避免每次都要去仓库&#xff08;磁盘&#xff09;取货。今天我们就…

使用numpy的快速傅里叶变换的一些问题

离散傅里叶变换&#xff08;DFT&#xff09;的频率&#xff08;或波数&#xff09;确实主要由采样点数和物理步长决定。 最高波数和最小波长的乘积是1。单位长度内波的周期数。 &#xff08;注意角波数是 k 2 π λ k \frac{2 \pi}{\lambda} kλ2π​&#xff09; 使用numpy…

DVWA靶场通关笔记-CSRF(High级别)

目录 一、CSRF Token 二、代码审计&#xff08;High级别&#xff09; 1、渗透准备 2、源码分析 三、渗透实战 1、渗透准备 2、修改URL重放失败 3、burpsuite尝试重放失败 4、安装CSRF Token Tracker 5、安装logger插件 6、配置CSRF Token Tracker 7、bp再次重放报文…

Redis实战:数据安全与性能保障

数据安全 持久化策略 RDB持久化&#xff1a;通过创建快照将内存中的数据写入到磁盘上的RDB文件中。可以在配置文件中设置save参数来指定在多少秒内有多少次写操作时触发快照保存。例如&#xff0c;save 900 1表示900秒内至少有1次写操作时保存快照。 AOF持久化&#xff1a;将每…

人脸活体识别3:C/C++实现实时眨眼、张嘴、点头、摇头检测

> 当AI能识破照片与真人的区别,我们才真正跨入生物识别安全时代 --- ### 一、活体检测:数字世界的守门人 **传统人脸识别的致命缺陷**: - 高清照片欺骗成功率 > 85% - 视频回放攻击成本 < $50 - 3D面具破解率高达72% **我们的解决方案**: ```mermaid graph …

【Linux】AlmaLinux 无法使用root用户登录cockpit控制台问题解决

在虚拟机安装AlmaLinux 9.6&#xff0c;安装过程中需要允许使用root用户和SSH协议登录服务器。但是&#xff0c;在使用root用户登录cockpit管理后台时&#xff0c;系统提示“权限被拒绝”。 经过查询资料&#xff0c;可以通过下面的方法来解决此问题。 编辑 /etc/cockpit/disa…

【Java面试】讲讲HashMap的常用方法,以及底层实现?

1. 底层数据结构 数组链表红黑树&#xff08;JDK 1.8&#xff09;&#xff1a; 数组&#xff08;Node[] table&#xff09;存储桶&#xff08;bucket&#xff09;&#xff0c;每个桶是链表或红黑树的头节点。链表解决哈希冲突&#xff0c;当链表长度 ≥ 8 且数组容量 ≥ 64 时…

ToT:思维树:借助大语言模型进行审慎的问题求解

摘要 语言模型正日益被部署于广泛任务中的通用问题求解&#xff0c;但在推理阶段仍受限于 token 级、从左到右的决策过程。这意味着在需要探索、战略前瞻&#xff0c;或初始决策起关键作用的任务中&#xff0c;语言模型可能表现不佳。为克服这些挑战&#xff0c;我们提出了一种…

Web3 + RWA 餐饮数字化解决方案白皮书(试点版)

一、背景&#xff1a;从“用户”到“共创股东”&#xff0c;重构本地生活新逻辑 ✨ 項目愿景&#xff1a; “用一顿饭&#xff0c;链接一个社群&#xff1b;用一次消费&#xff0c;绑定一份权益”。 传统商业以“交易”为中心&#xff0c;未来商业则以“关系 价值流转”为核…

MCU的模拟输入ADC引脚如何实现采样时间与阻抗匹配

在MCU的模拟输入ADC引脚中&#xff0c;实现采样时间与阻抗匹配是关键的设计环节&#xff0c;直接影响采样精度。以下是分步说明&#xff1a; 【】理解信号源阻抗与采样时间的关系 • 信号源阻抗&#xff08;Rs&#xff09;&#xff1a;外部信号源的输出阻抗&#xff08;如传感器…

等价矩阵 线性代数

所谓等价矩阵&#xff0c;就是说其秩相同的矩阵。 例题 A和B等价就是求A和B的秩&#xff0c;其实就是要求B的秩了&#xff0c;因为目标已经告诉你了A和B的秩是一样的。那么怎么求B的秩呢&#xff1f;我们现在只有一种方法求其秩&#xff0c;就是通过把其经过初等变换之后符合标…

30.设计模式的优缺点

原文地址:设计模式的优缺点 更多内容请关注&#xff1a;智想天开 一、设计模式的优点 1. 提高代码复用性与可维护性 复用性&#xff1a; 设计模式提供的是抽象的解决方案&#xff0c;可以在多个项目中重复应用&#xff0c;避免重复造轮子。例如&#xff0c;工厂模式封装了对象…

Python 爬虫实战 | 国家医保

一、国家医保 1、目标网站 网址&#xff1a;https://fuwu.nhsa.gov.cn/nationalHallSt/#/search/drug-directory目标数据&#xff1a;获取药品信息 2、网站特点 服务端返回加密数据&#xff0c;客户端发送请求携带的载荷也是加密的 3、定位解密入口 可以通过关键字encDa…

OpenCV CUDA模块设备层----计算向量的平方根函数sqrt

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 OpenCV 的 CUDA 设备函数&#xff08;device function&#xff09;&#xff0c;用于在 GPU 上计算一个 uchar4 类型向量的平方根&#xff0c;并返…

鸿蒙应用开发:HTTP访问网络

一、HTTP概述 在许多场景下&#xff0c;我们的应用需要从服务端获取数据&#xff0c;例如&#xff0c;天气应用需要从天气服务器获取天气数据。新闻应用需要从新闻服务器获取最新的新闻咨询&#xff0c;通过HTTP数据请求&#xff0c;我们可以将互联网上的信息展示在应用中&…