java多数据源透明切换的核心是通过abstractroutingdatasource路由中枢、threadlocal上下文绑定及aop声明式注解实现,使业务代码无需感知底层数据库差异。

Java 实现多数据源的透明切换,核心是把“切哪个库”这件事从业务代码里拿掉,让开发者写 SQL 或调用 Mapper 时完全感知不到底层连的是 MySQL、达梦还是从库。这不是靠手动换 DataSource 对象,而是靠一套路由机制 + 上下文绑定 + 框架集成来完成的。
基于 AbstractRoutingDataSource 的路由中枢
Spring 原生提供的 AbstractRoutingDataSource 是透明切换的基石。它本身不持有连接,只负责在运行时根据一个 key 查表,返回对应的真实 DataSource。
- 你需要继承它,并重写 determineCurrentLookupKey() 方法——这个方法返回什么,就决定走哪个数据源
- 真实的数据源(如 master、slave、dameng)以 Map 形式注入进去,key 就是 determineCurrentLookupKey 返回的值
- 整个过程对 MyBatis 或 JPA 透明:它们只认你配的那个 dynamicDataSource Bean,完全不知道背后有多个物理库
用 ThreadLocal 绑定当前线程的数据源意图
光有路由还不行,得让每次请求知道“这次该走谁”。最常用且可靠的方式是用 ThreadLocal 存一个标识(比如 "slave" 或 "dameng"),并在 determineCurrentLookupKey 中读取它。
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 定义一个上下文工具类,提供 set()、get()、clear() 方法
- 务必在每次请求结束(如 Filter 或 AOP 后置)调用 clear(),否则线程池复用会导致数据源错乱
- 这个标识可以是字符串、枚举,甚至租户 ID,取决于你的业务规则
通过 AOP + 自定义注解实现声明式切换
这是真正达成“透明”的关键一步。你不用在 service 方法里写 setDataSource("slave"),只需加个注解:
- 定义 @DataSource("slave") 注解,支持类级和方法级
- 写一个切面,在目标方法执行前读取该注解,调用上下文工具类 set();方法结束后 clear()
- 这样所有被标注的方法自动走指定库,业务代码零侵入
- 还可以配合规则扩展:比如读操作默认走从库,写操作强制走主库(结合方法名或事务注解判断)
整合 MyBatis-Plus 或通用 ORM 层
确保整个持久层链路都走动态数据源:
- SqlSessionFactory 的 dataSource 必须指向你定义的 DynamicDataSource Bean,不能直接引用 master 或 slave
- 如果用 MyBatis-Plus,确认其内置的 DataSource 是动态的;若用 dynamic-datasource-spring-boot-starter,它已帮你封装好这层
- 事务管理器 PlatformTransactionManager 的 dataSource 也要指向同一个 DynamicDataSource,否则 @Transactional 会失效或跨库出错
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










