Spring Boot Starter设计实现

前言

Starter 是 Spring Boot 非常重要的一个硬核功能。
通过 Starter 我们可以快速的引入一个功能或模块,而无须关心模块依赖的其它组件。关于配置,Spring Boot 采用“约定大于配置”的设计理念,Starter 一般都会提供默认配置,只有当我们有特殊需求的时候,才需要在application.yaml里进行单独配置以覆盖掉默认配置。

例如,我们开发一个 Web 应用,需要用到 Spring MVC、Tomcat 等组件,我们只需要依赖spring-boot-starter-web 即可,Starter 已经包含了开发一个 Web 应用所需的所有组件和依赖包,同时提供了 Web 服务的默认配置,比如端口是 8080。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

当我们有特殊需求时,比如要修改服务端口,才需要额外配置application.yaml

server:port: 8090

理解Starter

Starter 是什么???
Starter 是一个 Spring Boot 项目,它包含了一个功能或模块依赖的所有组件。一般来说,Starter 项目本身不包含任何代码,只管理依赖。

Starter 要解决什么问题???
没有 Starter 的时候,我们要引入一个功能或模块,首先要了解这个功能或模块依赖了哪些组件,还要管理依赖的版本。依赖完以后,还要配置所需的 bean,以及其它一些配置文件的编写。整个过程极其繁琐,门槛高。
Starter 解决了依赖和配置的问题,它把所需的依赖打成一个包,得益于 Spring Boot 自动装配,同时解决了 bean 的配置问题。引入 Starter 就可以实现零配置或少量配置来使用相应的功能。

Starter 是怎么实现的???
Starter 依赖 Spring Boot 自动装配的特性,它首先包含模块依赖的所有第三方库,再通过若干个XXXAutoConfiguration 的自动配置类来声明模块所需的 Bean,Spring Boot 程序启动时会自动加载这些配置类,把对应的 Bean 注册到容器,以实现某个功能。

Starter实战

通过编写一个我们自己的 Starter 来进一步理解其原理。
需求:编写一个可以操作 Redis 的客户端 Starter。
项目结构

redis-client- client- redis-spring-boot- redis-spring-boot-starter- redis-spring-boot-autoconfigure

模块介绍

模块说明
redis-client父项目,管理依赖
clientRedis 客户端核心模块
redis-spring-bootRedis 客户端和 Spring Boot 整合模块
redis-spring-boot-starterRedis 客户端启动器
redis-spring-boot-autoconfigureRedis 客户端自动装配模块(核心)

redis-client
基础模块,没有代码,主要管理依赖。因为要操作 Redis,这里引入 jedis。

<dependencyManagement><dependencies><dependency><groupId>io.redis</groupId><artifactId>client</artifactId><version>${project.version}</version></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.4.6</version></dependency></dependencies>
</dependencyManagement>

client
client 是 Redis 客户端核心模块,提供了操作 Redis 的客户端实现。它应该被设计成可以脱离 Spring 独立运行的,所以这个项目不应该依赖 Spring 任何东西。
首先抽象一个客户端接口,出于简单考虑,这里只提供 get、set 方法

public interface RedisClient {void set(String key, String value);String get(String key);
}

同时提供一个默认实现,这里只是对 jedis 做一层包装

public class DefaultRedisClient implements RedisClient {private final Jedis jedis;public DefaultRedisClient(Jedis jedis) {this.jedis = jedis;}@Overridepublic void set(String key, String value) {jedis.set(key, value);}@Overridepublic String get(String key) {return jedis.get(key);}
}

再提供一个工厂类,用来创建客户端实例

public class RedisClientFactory {public static RedisClient create(String host, int port, String user, String password, int database) {JedisClientConfig config = DefaultJedisClientConfig.builder().user(user).password(password).database(database).build();Jedis jedis = new Jedis(host, port, config);return new DefaultRedisClient(jedis);}
}

至此,client 模块就完成了,而且是可以直接跑的,无需 Spring。

redis-spring-boot
为了开发者更加方便的在 Spring Boot 环境下使用我们的 Redis Client,我们要和 Spring Boot 做一个整合,为此再单独新建一个 redis-spring-boot 模块。它是一个父模块,主要管理依赖

<dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.7.18</version></dependency><dependency><groupId>io.redis</groupId><artifactId>redis-spring-boot-autoconfigure</artifactId><version>${project.version}</version></dependency></dependencies>
</dependencyManagement>

redis-spring-boot-starter
我们的 Starter 模块,也就是开发者要引入的唯一一个模块。模块的命名上大家要注意,spring-boot-starter-XXX 这种前缀是 Spring Boot 官方保留的名字,我们不要用,建议用XXX-spring-boot-starter 风格命名。
Starter 模块一般没有代码,只管理依赖的组件,这里主要是引入我们的自动装配模块

<dependencies><dependency><groupId>io.redis</groupId><artifactId>redis-spring-boot-autoconfigure</artifactId></dependency>
</dependencies>

redis-spring-boot-autoconfigure
Redis Client 与 Spring Boot 整合的自动装配模块,也是我们这个示例中的核心模块。先看依赖:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>io.redis</groupId><artifactId>client</artifactId></dependency>
</dependencies>

RedisClientAutoConfiguration:自动配置类,Spring Boot 启动时会自动加载。它的加载是有条件的,首先得是 ClassPath 下包含 RedisClient.class,没有这个类我们就没法自动装配;其次是redis.enabled 不配置或者必须为 true 才会启用,否则是禁用的。

@Configuration
@ConditionalOnClass(RedisClient.class)
@ConditionalOnProperty(prefix = "redis",name = {"enabled"},matchIfMissing = true
)
@EnableConfigurationProperties(RedisClientProperties.class)
public class RedisClientAutoConfiguration {@Beanpublic RedisClient redisClient(RedisClientProperties properties) {return RedisClientFactory.create(properties.getHost(), properties.getPort(),properties.getUser(), properties.getPassword(), properties.getDatabase());}
}

自动配置类还开启了自动配置属性,类是 RedisClientProperties。按照“约定大于配置”的理念,我们提供了默认配置,开发者也可以选择覆盖默认配置

@ConfigurationProperties(prefix = "redis",ignoreUnknownFields = true
)
public class RedisClientProperties {private String host = "localhost";private int port = 6379;private String user;private String password;private int database = 0;// 忽略 getter、setter
}

最后,要想办法让 Spring Boot 加载我们的配置类。按照 Spring Boot 自动装配的规则,我们编写META-INF/spring.factories文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\io.redis.client.spring.boot.autoconfigure.RedisClientAutoConfiguration

至此,我们的 Starter 就开发完毕了,把它安装到 Maven 仓库就可以给其它小伙伴用了。

测试一下
新建一个测试项目,引入依赖

<dependencies><dependency><groupId>io.redis</groupId><artifactId>redis-spring-boot-starter</artifactId><version>1.0-SNAPSHOT</version></dependency>
</dependencies>

编写一个启动类,注入 RedisClient,尝试读取一下数据,是成功的

@SpringBootApplication
public class Application {@AutowiredRedisClient redisClient;public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);RedisClient redisClient = context.getBean(Application.class).redisClient;redisClient.set("haha", "xixi");System.err.println(redisClient.get("haha"));}
}

尾巴

Starter 是 Spring Boot 框架中的一个重要概念,它提供了一种便捷的方式来配置和使用特定功能的 Spring Boot 应用程序。通常一个 Starter 是一个包含了一组相关依赖和配置的项目,目的是为了简化应用程序的开发和部署过程。
Starter 的设计目标是通过隐藏繁琐的配置细节和依赖声明,使开发者能够更专注于业务逻辑的实现。当你想要使用某个功能或集成某个组件时,只需引入相应的 Starter 依赖,Spring Boot 就会自动配置相关的组件,并提供默认的配置选项,大大减少了手动配置的工作量。
Starter 依赖于 Spring Boot 自动装配的特性,理解了自动装配你就理解了 Starter。

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

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

相关文章

Python脚本——.csv文件转.txt脚本三则

第一则 """ 批量给指定文件夹内的所有.csv文件增加表头后转成txt """import osdef add_header_and_convert_to_txt(csv_folder, header, output_folder):# 获取指定文件夹中的所有.csv文件csv_files [f for f in os.listdir(csv_folder) if f.…

LeetCode讲解篇之2280. 表示一个折线图的最少线段数

文章目录 题目描述题解思路题解代码 题目描述 题解思路 折线图中如果连续的线段共线&#xff0c;那么我们可以可以将其合并成一条线段 首先将坐标点按照横坐标升序排序 然后遍历数组 我们可以通过计算前一个线段的斜率和当前线段的斜率来判断是否共线 如果二者相等&#x…

【Linux常用的基本指令】

Linux学习笔记---002 Linux的基本指令1、ls指令2、pwd指令3、mkdir指令4、cd指令5、alias命令6、clear指令7、touch指令8、rmdir指令9、rm指令10、man指令11、cp指令12、mv指令13、cat指令14、more指令15、less指令16、时间相关的指令16.1、date指令16.2、cal指令 17、find指令…

Python之字符串中常用的方法

1. 去掉空格和特殊符号 name " abcdefgeyameng " name1 name.strip() # 并不会在原来的字符串上操作,返回一个去除了两边空白的字符串 print(name1, len(name1), name, len(name)) # abcdefgeyameng 14 abcdefgeyameng 17 # 去掉左边的空格和换行符 name2 n…

测试SpringBoot的时候报错mapper未装载的解决方案:

1.报错信息和截图&#xff1a; org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name com.tang.testspringboot.TestSpringBootApplicationTests: Unsatisfied dependency expressed through field mapper: No qualifying bean o…

Python3.10安装教程

Python3.10安装 Python的安装按照下面几步进行即可&#xff0c;比较简单。 下载Python安装文件&#xff0c;打开Python的下载页面&#xff0c;我这里选择安装的版本是3.10.11&#xff0c;根据自己电脑版本选择对应安装包 安装包下载完毕后&#xff0c;按照步骤开始安装。选择…

620基于51单片机的密码锁设计[Proteus仿真]

620基于51单片机的密码锁设计[proteus仿真] 密码锁设计这个题目算是课 程设计和毕业设计中常见的题目了&#xff0c;本期是一个基于51单片机的密码锁设计 需要的源文件和程序的小伙伴可以关注公众号【阿目分享嵌入式】&#xff0c;赞赏任意文章 2&#xffe5;&#xff0c;私信…

springboot集成钉钉通知

目录 1.通过自定义机器人方式发送群消息 1.1说明 1.2发送普通消息示例&#xff08;采用加签方式&#xff09; 1.3注意事项 2.通过企业内部应用发送钉钉消息 2.1说明 2.2示例 2.3注意 1.通过自定义机器人方式发送群消息 1.1说明 官网地址&#xff1a; 自定义机器人发送…

2024年江苏省信息安全管理与评估理论题题库(单选120题,多选40题)

2024年江苏省信息安全管理与评估理论题题库(单选120题,多选40题) 因各方面原因,无法公开发布,只能设为vip文章,有需要的小伙伴可以看看。 单选题 PGP是一个基于下列哪个公钥加密体系的邮件加密软件?( )A.RSA B.Kerberos C.DES D.IDEA 防火墙通过( )控制来阻塞邮…

this.setState的注意事项

目录 1、this.setState的注意事项 2、是什么造成了this.setState()的不同步&#xff1f; 3、 那this.setState()什么时候同步&#xff0c;什么时候不同步&#xff1f; 3.1 经过React包装的onClick点击事件&#xff08;&#xff09; 3.2 没经过React包装的 原生点击事件 …

嘘……快进来!这儿有最新版Microsoft照片程序的安装秘籍!(附安装引导程序下载)

网管小贾 / sysadm.cc 最近啊有不少小伙伴向我反馈&#xff0c;自个的 Windows 10 系统里边居然没有 Microsoft 照片 程序。 我觉得有点不可思议&#xff0c;为啥呢&#xff0c;因为他们的电脑是新买的&#xff01; 你看哈&#xff0c;系统是 22H2 最新版&#xff0c;安装日期…

vscode打开c_cpp_properties.json文件的一种方式

步骤一 点击win32 步骤二 点击json 自动生成了

鸿蒙Harmony-线性布局(Row/Column)详解

人生的下半场&#xff0c;做个简单的人&#xff0c;少与人纠缠&#xff0c;多看大自然&#xff0c;在路上见世界&#xff0c;在途中寻自己。往后余生唯愿开心健康&#xff0c;至于其他&#xff0c;随缘就好&#xff01; 目录 一&#xff0c;定义 二&#xff0c;基本概念 三&am…

如何使用“通义听悟”提高工作和学习效率

如何使用通义听悟提高工作和学习效率 通义听悟是一款利用人工智能技术&#xff0c;自动为音频和视频内容提供转写、翻译、总结、检索等功能的在线工具。它可以在会议、学习、访谈、培训等场景下&#xff0c;帮助您记录、阅读、整理、复习音视频信息&#xff0c;成为您的工作和…

FPGA 移位运算与乘法

题目&#xff1a; 已知d为一个8位数&#xff0c;请在每个时钟周期分别输出该数乘1/3/7/8,并输出一个信号通知此时刻输入的d有效&#xff08;d给出的信号的上升沿表示写入有效&#xff09; 由题意可知&#xff1a; 复位信号高有效&#xff0c;低复位&#xff1b;在inpu_grant上升…

WorkPlus卓越的即时通讯工具,助力企业提升工作效率

在当今快节奏的商业环境中&#xff0c;高效沟通和协作是企业成功的关键。而即时通讯作为实现高效沟通的利器&#xff0c;成为了现代企业不可或缺的一部分。作为一款领先的即时通讯工具&#xff0c;WorkPlus以其卓越的性能和独特的功能&#xff0c;助力企业打造高效沟通和协作的…

HTTP API 认证技术详解(二):Digest Access Authentication

目录 什么是 Digest Access Authentication 认证 Digest Access Authentication 认证的原理 Digest Access Authentication 认证的安全性 使用 Golang 实现 Digest Access Authentication 使用建议 小结 HTTP API 认证技术主要用于验证客户端身份&#xff0c;并确保只有经…

docker应用:搭建uptime-kuma监控站点

简介&#xff1a;Uptime Kuma是一个易于使用的自托管监控工具&#xff0c;它的界面干净简洁&#xff0c;部署和使用都非常方便。 历史攻略&#xff1a; docker&#xff1a;可视化工具portainer docker-compose&#xff1a;搭建自动化运维平台Spug 开源地址&#xff1a; ht…

【NI 国产替代】PXIe‑6378,16路AI(16位,3.5 MS/s/ch),4路AO,48路DIO,PXI多功能I/O模块

PXIe&#xff0c;16路AI&#xff08;16位&#xff0c;3.5 MS/s/ch&#xff09;&#xff0c;4路AO&#xff0c;48路DIO&#xff0c;PXI多功能I/O模块 PXIe‑6378是一款同步采样的多功能DAQ设备。 该模块提供了模拟 I/O、数字I/O、四个32位计数器和模拟和数字触发。 板载NI‑STC3…

class_3:lambda表达式

1、lambda表达式是c11引入的一种匿名函数的方式&#xff0c;它允许你在需要函数的地方内联的定义函数&#xff0c;而无需单独命名函数&#xff1b; #include <iostream>using namespace std;bool compare(int a,int b) {return a > b; }int getMax(int a,int b,bool (…