Spring Boot 多数据源解决方案:dynamic-datasource-spring-boot-starter 的奥秘

在 Spring Boot 生态中,dynamic-datasource-spring-boot-starter 是一个非常实用的组件,它为我们在多数据源场景下提供了便捷的解决方案。在上一篇文章《一分钟上手:如何创建你的第一个 Spring Boot Starter》中,我们学习了如何创建自己的 starter,今天我们就来深入探究下 dynamic-datasource-spring-boot-starter 的源码,了解它是如何实现动态数据源切换功能的。

一、dynamic-datasource-spring-boot-starter介绍

dynamic-datasource-spring-boot-starter 是一个用于在 Spring Boot 项目中实现动态数据源切换的工具

在实际的应用开发中,经常会遇到需要连接多个数据源的情况,例如一个销售系统会根据不同的业务模块,如线索、订单、库存、物流等连接到不同的数据库。手动管理多个数据源的切换和配置是一项复杂且容易出错的任务,而这个 starter 就是为了解决这些问题而生。

二、依赖的jar包

1. SpringBoot相关依赖

提供了JDBC数据库连接操作、AOP(面向切面编程)、Actuator应用监控、Web应用开发等功能,Actuator和Web依赖都是可选的,不是必须的

	<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><optional>true</optional></dependency>

2. MyBatis-Plus

增强版的MyBatis框架,可以极大简化数据库操作,业务的mapper层只需要继承BaseMapper,即可使用mybatis-plus提供的增删改查的API。使开发者能够更加专注于业务逻辑的实现,而无需在复杂的 SQL 编写和数据库连接管理上耗费过多精力。该jar包也是可选的,不是必须的

3. 连接池

HikariCP、Druid、Beecp、Commons DBCP2等用于管理数据库连接。
这些jar包也都是可选的,后端开发使用的最多的还是Druid数据库连接池

	<dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP-java7</artifactId><version>${hikariCp.version}</version><optional>true</optional></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>${druid.version}</version><optional>true</optional></dependency><dependency><groupId>com.github.chris2018998</groupId><artifactId>beecp</artifactId><version>${beeCp.version}</version><optional>true</optional></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-dbcp2</artifactId><version>${dbcp2.version}</version><optional>true</optional></dependency>

4. 配置处理器

在开发阶段为 IDE 提供辅助功能,如代码提示和验证配置属性的正确性。在项目的实际运行时,并不需要这个依赖来执行应用程序的核心逻辑,所以也将其设置为可选,避免了不必要的依赖传递,减小了项目最终打包的体积

		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency>

5. P6Spy

用于监控和调试SQL语句。可能在开发和测试环境中非常有用,但在生产环境中可能不需要,所以业将其标记为可选依赖,让使用方根据实际情况决定是否引入。

6. Seata

提供分布式事务解决方案,根据项目实际需要决定要不要引入,所以该jar包也是可选的。

三、DynamicDataSourceAutoConfiguration类剖析

DynamicDataSourceAutoConfiguration类是dynamic-datasource-spring-boot-starter包的自动配置类,整个动态数据源的配置和初始化都在这里。

@Configuration
@EnableConfigurationProperties({DynamicDataSourceProperties.class})
@AutoConfigureBefore(value = {DataSourceAutoConfiguration.class},name = {"com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure"}
)
@Import({DruidDynamicDataSourceConfiguration.class, DynamicDataSourceCreatorAutoConfiguration.class, DynamicDataSourceHealthCheckConfiguration.class})
@ConditionalOnProperty(prefix = "spring.datasource.dynamic",name = {"enabled"},havingValue = "true",matchIfMissing = true
)
public class DynamicDataSourceAutoConfiguration {……
}

这种配置类相关的注解之前的博客也分享过,这里就不再赘述了,我们重点来剖析下该配置类中的几个关键方法。

1. dynamicDataSourceProvider方法

用于创建动态数据源提供者 DynamicDataSourceProvider。其主要职责是根据配置文件中的数据源信息构建数据源对象,并将其提供给动态数据源路由机制。

	@Bean@ConditionalOnMissingBean // 确保Spring容器中不存在 DynamicDataSourceProvider 类型的 Bean 时才创建该 Beanpublic DynamicDataSourceProvider dynamicDataSourceProvider() {Map<String, DataSourceProperty> datasourceMap = this.properties.getDatasource();return new YmlDynamicDataSourceProvider(datasourceMap);}

2. dataSource方法

用于是创建动态数据源 DynamicRoutingDataSource。它整合了各种配置信息,包括默认数据源、严格模式、切换策略、数据源提供者以及与SQL语句监控和分布式事务相关的配置,构建出一个完整的动态数据源对象,使其能够在运行时根据不同条件动态切换数据源。

	@Bean@ConditionalOnMissingBeanpublic DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();// 默认数据源dataSource.setPrimary(this.properties.getPrimary());// 根据配置决定在数据源切换时是否进行严格检查,以确保数据源的正确性和一致性。dataSource.setStrict(this.properties.getStrict());// 数据源切换策略,如基于注解、基于配置文件或基于特定规则的切换策略dataSource.setStrategy(this.properties.getStrategy());dataSource.setProvider(dynamicDataSourceProvider);dataSource.setP6spy(this.properties.getP6spy());dataSource.setSeata(this.properties.getSeata());return dataSource;}

3. dynamicDatasourceAnnotationAdvisor 方法

负责创建动态数据源注解切面的Advisor。用于在方法执行时根据注解信息进行数据源切换。

	@Role(2)@Beanpublic Advisor dynamicDatasourceAnnotationAdvisor(DsProcessor dsProcessor) {DynamicDataSourceAnnotationInterceptor interceptor = new DynamicDataSourceAnnotationInterceptor(this.properties.isAllowedPublicOnly(), dsProcessor);DynamicDataSourceAnnotationAdvisor advisor = new DynamicDataSourceAnnotationAdvisor(interceptor);advisor.setOrder(this.properties.getOrder());return advisor;}

4. dynamicTransactionAdvisor 方法

用于创建动态事务 Advisor。它定义了一个基于注解的事务切面,用于在方法执行时管理事务,确保数据库操作的原子性、一致性、隔离性和持久性。

	@Role(2)@ConditionalOnProperty(prefix = "spring.datasource.dynamic",name = {"seata"},havingValue = "false",matchIfMissing = true)@Beanpublic Advisor dynamicTransactionAdvisor() {AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();pointcut.setExpression("@annotation(com.baomidou.dynamic.datasource.annotation.DSTransactional)");return new DefaultPointcutAdvisor(pointcut, new DynamicLocalTransactionAdvisor());}

5. dsProcessor 方法

用于创建数据源处理器 DsProcessor。数据源处理器负责根据不同的条件(如请求头、会话信息、SpEL 表达式等)确定要切换的数据源,是实现动态数据源切换逻辑的关键组件之一。

自动配置类剖析完了,剩下的就是配置属性类DynamicDataSourceProperties和spring.factories 文件了。

@ConfigurationProperties(prefix = "spring.datasource.dynamic"
)
public class DynamicDataSourceProperties {private static final Logger log = LoggerFactory.getLogger(DynamicDataSourceProperties.class);public static final String PREFIX = "spring.datasource.dynamic";public static final String HEALTH = "spring.datasource.dynamic.health";public static final String DEFAULT_VALID_QUERY = "SELECT 1";private String primary = "master";private Boolean strict = false;private Boolean p6spy = false;private Boolean seata = false;private Boolean lazy = false;private SeataMode seataMode;private boolean health;private String healthValidQuery;private Map<String, DataSourceProperty> datasource;private Class<? extends DynamicDataSourceStrategy> strategy;private Integer order;@NestedConfigurationPropertyprivate DruidConfig druid;@NestedConfigurationPropertyprivate HikariCpConfig hikari;@NestedConfigurationPropertyprivate BeeCpConfig beecp;@NestedConfigurationPropertyprivate Dbcp2Config dbcp2;private String publicKey;private boolean allowedPublicOnly;……
}

DynamicDataSourceProperties一般都配置在Apollo中。

以下是spring.factories文件。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration

四、总结

通过对 dynamic-datasource-spring-boot-starter 的剖析,我们可以了解到它是实现动态数据源切换的机制。这一组件为开发者在处理多数据源场景时提供了极大的便利,使得应用的可扩展性和可维护性得到了显著提升。

下一篇博客我们将结合最佳实践来揭秘dynamic-datasource-spring-boot-starter组件的使用。

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

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

相关文章

Servlet学习中遇到的一些问题及解决

错误&#xff1a;JavaWeb-错误&#xff1a;类xxx不是Servlet 解决&#xff1a;可能是Tomcat版本不匹配导致&#xff0c;更换Tomcat版本解决问题 错误&#xff1a;在自定义的Servlet类中不能添加 WebServlet 注解 解决&#xff1a;可能是WebServlet版本不匹配&#xff0c;更换…

tomcat的安装以及配置(基于linuxOS)

目录 安装jdk环境 yum安装 验证JDK环境 安装tomcat应用 yum安装 ​编辑 使用yum工具进行安装 配置tomcat应用 关闭防火墙和selinux 查看端口开启情况 ​编辑 访问tomcat服务 安装扩展包 重启服务 查看服务 源码安装 进入tomcat官网进行下载 查找自己要用的to…

workman服务端开发模式-应用开发-gateway长链接端工作原理

一、长链接的工作原理 Register类其实也是基于基础的Worker开发的。Gateway进程和BusinessWorker进程启动后分别向Register进程注册自己的通讯地址&#xff0c;Gateway进程和BusinessWorker通过Register进程得到通讯地址后&#xff0c;就可以建立起连接并通讯了。而Gateway进程…

Chrome 浏览器原生功能截长屏

我偶尔需要截取一些网页内容作为素材&#xff0c;但偶尔内容很长无法截全&#xff0c;需要多次截屏再拼接&#xff0c;过于麻烦。所以记录下这个通过浏览器原生功能截长屏的方案。 注意 这种方案并不是百分百完美&#xff0c;如果涉及到一些需要滚动加载的数据或者悬浮区块&am…

Kubeadm+Containerd部署k8s(v1.28.2)集群(非高可用版)

Kubeadm+Containerd部署k8s(v1.28.2)集群(非高可用版) 文章目录 Kubeadm+Containerd部署k8s(v1.28.2)集群(非高可用版)一.环境准备1.服务器准备2.环境配置3.设置主机名4.修改国内镜像源地址5.配置时间同步6.配置内核转发及网桥过滤二.容器运行时Containerd安装(所有节点)…

Nuc9 Truenas 和 Macmini4组雷电网桥 上传速度异常 1Mbp/s 解决

link: 原创文章&#xff0c;转载之前请标注来源博客 helsonlin 前言 咸鱼整了一台 Nuc9 组了全闪的 Nas&#xff0c;想着和 Macmini 组雷电网桥&#xff0c;但是到手弄好之后发现 iperf3 和 openspeedtest 测试上传的速度都是 1Mbps 每秒。 Google 一下发现唯一的线索就是ht…

Python从0到100(七十八):神经网络--从0开始搭建全连接网络和CNN网络

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…

Qt:QMetaObject::connectSlotsByName实现信号槽自动关联

简介 在Qt中&#xff0c;QMetaObject::connectSlotsByName 是一个便利的方法&#xff0c;它可以根据对象的对象名&#xff08;objectName&#xff09;自动将信号和槽连接起来。但是&#xff0c;要使用这个方法&#xff0c;必须确保&#xff1a; 1 控件&#xff08;如按钮&…

数据挖掘之认识数据

在数据挖掘过程中&#xff0c;数据的认识是非常重要的一步&#xff0c;它为后续的数据分析、建模、特征选择等工作奠定基础。以鸢尾花数据集&#xff08;Iris Dataset&#xff09;数据集之鸢尾花数据集&#xff08;Iris Dataset&#xff09;-CSDN博客为例&#xff0c;下面将介绍…

useContext Hook 的使用及规范

首先 useContext 是什么&#xff1f; useContext 是 React 提供的一个 Hook&#xff0c;允许函数组件订阅 React 的 Context。 有什么用&#xff1f; 它使得你可以在不使用 Consumer 组件的情况下访问 Context 的值。通过 useContext&#xff0c;你可以轻松地在多层级组件之间…

MacOS 命令行详解使用教程

本章讲述MacOs命令行详解的使用教程&#xff0c;感谢大家观看。 本人博客:如烟花般绚烂却又稍纵即逝的主页 MacOs命令行前言&#xff1a; 在 macOS 上,Terminal&#xff08;终端) 是一个功能强大的工具&#xff0c;它允许用户通过命令行直接与系统交互。本教程将详细介绍 macOS…

Mac上详细配置java开发环境和软件(更新中)

文章目录 概要JDK的配置JDK下载安装配置JDK环境变量文件 Idea的安装Mysql安装和配置Navicat Premium16.1安装安装Vscode安装和配置Maven配置本地仓库配置阿里云私服Idea集成Maven Cpolar快速入门 概要 这里使用的是M3型片 14.6版本的Mac 用到的资源放在网盘 链接: https://pan…

Neo4j 图数据库安装与操作指南(以mac为例)

目录 一、安装前提条件 1.1 Java环境 1.2 Homebrew&#xff08;可选&#xff09; 二、下载并安装Neo4j 2.1 从官方网站下载 2.1.1 访问Neo4j的官方网站 2.1.2 使用Homebrew安装 三、配置Neo4j 3.1 设置环境变量(可选) 3.2 打开配置文件(bash_profile) 3.2.1 打开终端…

【数据结构练习题】链表与LinkedList

顺序表与链表LinkedList 选择题链表面试题1. 删除链表中等于给定值 val 的所有节点。2. 反转一个单链表。3. 给定一个带有头结点 head 的非空单链表&#xff0c;返回链表的中间结点。如果有两个中间结点&#xff0c;则返回第二个中间结点。4. 输入一个链表&#xff0c;输出该链…

图书借阅管理系统|SpringBoot|HTML|web网站|Java【源码+数据库文件+包部署成功+答疑解惑问到会为止】

代码包运行启动成功&#xff01;不管你有没有运行环境&#xff0c;哪怕你是刚买的新电脑&#xff0c;也包启动运行成功&#xff01;有不懂的地方随便问&#xff01;问到会为止&#xff01; 【功能介绍】 该系统有两种角色&#xff1a; 管理员&#xff0c;读者。 1.管理员可以添…

Qt Quick:CheckBox 复选框

复选框不止选中和未选中2种状态哦&#xff0c;它还有1种部分选中的状态。这3种状态都是Qt自带的&#xff0c;如果想让复选框有部分选中这个状态&#xff0c;需要将三态属性&#xff08;tristate&#xff09;设为true。 未选中的状态值为0&#xff0c;部分选中是1&#xff0c;选…

【ue5学习笔记2】在场景放入一个物体的蓝图输入事件无效?

在场景放入一个物体的蓝图输入事件无效&#xff0c;那是因为你不知道gameMode这个东西这是一个用于设定游戏股则的东西&#xff0c; 就好比你的控制对象&#xff0c;你输入无效是没有指定你当前关卡中指定的控制对象是它。操作方法如下&#xff1a; 1.创建一个gameMode蓝图类并…

pro文件转换为CMakeLists.txt文件,QT官方工具使用教程

某些情况需要使用cmake&#xff0c;如果手动将QT的pro文件转换成CMakeLists.txt&#xff0c;简短一点的pro还好&#xff0c;如果是比较复杂的pro&#xff0c;手动转换的时候需要长时间的debug&#xff0c;本人深有感受。 工具介绍&#xff1a; qmake2cmake工具创建一个CMakeL…

Python读取Excel批量写入到PPT生成词卡

一、问题的提出 有网友想把Excel表中的三列数据&#xff0c;分别是&#xff1a;单词、音标和释义分别写入到PPT当中&#xff0c;每一张PPT写一个单词的内容。这种批量操作是python的强项&#xff0c;尤其是在办公领域&#xff0c;它能较好地解放双手&#xff0c;读取Excel表后…

【快速上手】linux环境下Neo4j的安装与使用

一、neo4j简介 neo4j是一个非关系型图形数据库&#xff0c;非常适合处理具有复杂关系的数据集 存储方式&#xff1a;图形化存储 特点&#xff1a;将结构化数据存储在图上而不是表&#xff08;比如&#xff1a;MySQL数据库存储在表中&#xff09;中 neo4j也可以看作是一个高…