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 的剖析,我们可以了解到它是实现动态数据源切换的机制。这一组件为开发者在处理多数据源场景时提供了极大的便利,使得应用的可扩展性和可维护性得到了显著提升。
相关文章:
Spring Boot 多数据源解决方案:dynamic-datasource-spring-boot-starter 的奥秘(上)
在 Spring Boot 生态中,dynamic-datasource-spring-boot-starter 是一个非常实用的组件,它为我们在多数据源场景下提供了便捷的解决方案。在上一篇文章《一分钟上手:如何创建你的第一个 Spring Boot Starter》中,我们学习了如何创…...
[NewStarCTF 2023 公开赛道]ez_sql1 【sqlmap使用/大小写绕过】
题目: 发现id处可以sql注入: 虽然输入id1;show databases;#没什么回显,但是知道这里是字符型注入了 这次利用sqlmap注入 --dbs:列出所有数据库名字 python .\sqlmap.py -u http://a40b2f0a-823f-4c99-b43c-08b94ed0abb2.node5.…...
【商城实战(18)】后台管理系统基础搭建:从0到1构建电商中枢
【商城实战】专栏重磅来袭!这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建,运用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用户、商品、订单等核心模块开发,再到性能优化、安全加固、多端适配…...
新能源汽车充电综合解决方案:安科瑞电气助力绿色出行
安科瑞 华楠 18706163979 随着新能源汽车的迅猛发展,充电基础设施的建设成为了推动行业进步的关键。然而,充电技术滞后、运营效率低下、车桩比失衡等问题,依然困扰着广大车主和运营商。今天,我们要为大家介绍一款新能源汽车充电…...
蓝桥杯java-B组真题—动态规划
目录 一.什么是动态规划? 二.题目 第一种情况:集合本身之和为奇数 第二种情况:集合本身之和为偶数 下面是代码实现: 一.什么是动态规划? 这里就简单的解释一下,动态规划就是记录之前的计算结果,避免重复的计算之前已经计算过的结果,用…...
【网络编程】事件选择模型
十、基于I/O模型的网络开发 10.9 事件选择模型 10.0.1 基本概念 事件选择(WSAEventSelect) 模型是另一个有用的异步 I/O 模型。和 WSAAsyncSelect 模 型类似的是,它也允许应用程序在一个或多个套接字上接收以事件为基础的网络事件通知,最 主要的差别在…...
网易邮箱如何用大数据任务调度实现海量邮件数据处理?Apache DolphinScheduler用户交流会上来揭秘!
你是否对大数据领域的前沿应用充满好奇?网易邮箱作为互联网大厂网易的重要业务线,在大数据应用方面有着诸多值得借鉴的实践经验。你是否渴望深入了解网易邮箱如何借助 Apache DolphinScheduler 实现海量邮件数据处理、用户行为分析、实时监控等核心业务场…...
前端知识点---路由模式-实例模式和单例模式(ts)
在 ArkTS(Ark UI 框架)中,路由实例模式(Standard Instance Mode)主要用于管理页面跳转。当创建一个新页面时,可以选择标准实例模式(Standard Mode)或单实例模式(Single M…...
固定表头、首列 —— uniapp、vue 项目
项目实地:也可以在 【微信小程序】搜索体验:xny.handbook 另一个体验项目:官网 一、效果展示 二、代码展示 (1)html 部分 <view class"table"><view class"tr"><view class&quo…...
langchain系列(九)- LangGraph 子图详解
目录 一、导读 二、原理说明 1、简介 2、子图图示 3、使用说明 三、基础代码实现 1、实现功能 2、Graph 图示 3、代码实现 4、输出 5、分析 四、人机交互 1、实现中断 2、历史状态(父图) 3、历史状态(子图) 4、历史…...
搜索引擎是如何理解你的查询并提供精准结果的?
目录 一、搜索引擎简单介绍 二、搜索引擎整体架构和工作过程 (一)整体分析 (二)爬虫系统 三个基本点 爬虫系统的工作流程 关键考虑因素和挑战 (三)索引系统 网页处理阶段 预处理阶段 反作弊分析…...
【前端】【组件】【vue2】封装一个vue2的ECharts组件,不用借助vue-echarts
在Vue2项目中使用ECharts 5.6的完整实现步骤如下: 安装依赖 npm install echarts5.6.2 --save # 指定安装5.x最新版本基础组件实现(新建components/ECharts.vue) <template><div ref"chartDom" class"echarts-co…...
18天 - 常见的 HTTP 状态码有哪些?HTTP 请求包含哪些内容,请求头和请求体有哪些类型?HTTP 中 GET 和 POST 的区别是什么?
常见的 HTTP 状态码有哪些? HTTP 状态码用于指示服务器对客户端请求的响应结果,常见的 HTTP 状态码可以分为以下几类: 1. 信息类(1xx) 100 Continue:客户端应继续发送请求。101 Switching Protocols&…...
IDEA软件安装环境配置中文插件
一、Java环境配置 1. JDK安装8 访问Oracle官网下载JDK8(推荐JDK8,11)Java Downloads | Oracle 双击安装程序,保持默认设置连续点击"下一步"完成安装 验证JDK安装,winR键 然后输入cmd,输入java…...
循环神经网络(RNN):时序建模的核心引擎与演进之路
在人工智能处理序列数据的战场上,循环神经网络(RNN)如同一个能够理解时间的智者。从 2015 年谷歌神经机器翻译系统颠覆传统方法,到 2023 年 ChatGPT 实现对话连续性,这些突破都植根于 RNN 对时序建模的深刻理解。本文将…...
HTML 表单 (form) 的作用解释
表单在网页中主要负责的是数据采集功能,一个表单基本由三部分组成: 表单标签:这里面包含了处理表单数据所用 CGI (Common Gateway Interface,通用网关接口)程序的 URL (Uniform Resource Locati…...
Windows控制台函数:控制台读取输入函数ReadConsoleA()
目录 什么是 ReadConsoleA? 它长什么样? 怎么用它? 它跟 std::cin 有什么不一样? 注意事项 什么是 ReadConsoleA? ReadConsoleA 是一个 Windows API 函数,用来从控制台读取用户输入。想象一下&#…...
网络tcp协议设置,网络tcp协议设置不了
网络TCP协议的设置通常涉及到多个方面,包括IP地址、子网掩码、默认网关、DNS服务器等参数的配置,以及TCP/IP协议栈本身的配置。如果遇到网络TCP协议设置不了的问题,可能是由多种原因导致的。以下是一些可能的原因及解决方法: 一、…...
电脑总显示串口正在被占用处理方法
1.现象 在嵌入式开发过程中,有很多情况下要使用串口调试,其中485/422/232转usb串口是非常常见的做法。 根据协议,接口芯片不同,需要安装对应的驱动程序,比如ch340,cp2102,CDM212364等驱动。可…...
R语言和RStudio安装
整体还是比较简单的,主要是记录个流程。 官方镜像站列表R语言官网 1 安装R(2025/3/6) R语言官网:The R Project for Statistical Computing 打开之后就Hello world一下吧 配置环境变量 2 安装RStudio 下载地址:htt…...
RHEL/CentOS 7.9使用firewalld限制出方向策略
背景 通常使用firewalld时候多为限制入方向访问,本次因有系统需要在生产环境部署测试环境,需求人希望在该测试环境中限制访问的对象,避免对生产造成影响 基础团队小伙伴参照rich-files,通过CLI,GUI反复进行进行配置验…...
设计模式之建造者模式:原理、实现与应用
引言 建造者模式(Builder Pattern)是一种创建型设计模式,它通过将复杂对象的构建过程分解为多个简单的步骤,使得对象的创建更加灵活和可维护。建造者模式特别适用于构建具有多个组成部分的复杂对象。本文将深入探讨建造者模式的原…...
1688店铺所有商品数据接口详解
一、接口概述淘宝开放平台提供 1688.items.onsale.get/taobao.item_search_shop 接口,可批量获取店铺在售商品列表,包含商品 ID、标题、价格、销量、图片等核心信息。该接口适用于商品库管理、竞品监控、数据分析等场景 二、接口调用流程 前期准…...
【C#学习笔记02】基本元素与数据类型
引言 深入了解C语言的基本元素、计算机存储器结构、常量与变量的概念以及数据类型。这些内容是C语言编程的基础,掌握它们对于编写高效、可靠的嵌入式程序至关重要。 1.C语言的基本元素 编程语言的发展离不开自然语言,所以编程语言的语法和词汇也是由…...
【语料数据爬虫】Python爬虫|批量采集工作报告数据(1)
前言 本文是该专栏的第4篇,后面会持续分享Python爬虫采集各种语料数据的的干货知识,值得关注。 在本文中,笔者将主要来介绍基于Python,来实现批量采集“工作报告”数据。同时,本文也是采集“工作报告”数据系列的第1篇。 采集相关数据的具体细节部分以及详细思路逻辑,笔…...
<建模软件安装教程1>Blender4.2系列
Blender4.2安装教程 0注意:Windows环境下安装 第一步,百度网盘提取安装包。百度网盘链接:通过网盘分享的文件:blender.zip 链接: https://pan.baidu.com/s/1OG0jMMtN0qWDSQ6z_rE-9w 提取码: 0309 --来自百度网盘超级会员v3的分…...
Docker极简部署开源播放器Splayer结合内网穿透远程流畅在线听歌
前言 嘿,各位音乐发烧友们!如果你厌倦了广告的打扰,渴望在忙碌的生活中找到一片宁静的音乐天地,那么今天这篇教程绝对适合你——如何在Ubuntu上用Docker快速搭建一款高颜值、无广告的某抑云音乐播放器Splayer。 Splayer不仅界面…...
基于YOLO(以YOLOv8为例)模型开发算法的详细步骤,包含算法代码、训练指导、数据集准备以及可能的改进方向
以下是一个基于YOLO(以YOLOv8为例)模型开发算法的详细步骤,包含算法代码、训练指导、数据集准备以及可能的改进方向。 1. 环境准备 首先,你需要安装必要的库。可以使用以下命令创建一个新的虚拟环境并安装所需的库: …...
显示器长时间黑屏
现象 电脑启动后,进入登录界面前会随机黑屏,有时候十几秒,有时候几分钟 进入桌面后,长时间不操作电脑黑屏,移动鼠标,点击键盘后尝试点亮屏幕,也会消耗较长时间 尝试 重装系统,或者重新安装显卡,都能够恢复,但过段时间以后又出现黑屏情况 集成显卡,独立显卡都出现过 操作系统…...
linux docker相关指令
1、镜像操作 0)、搜索:docker search 镜像名称 1)、拉取:docker pull 2)、推送:docker push 3)、查看:docker images 4)、查看所有镜像ID:d…...
