Java中JDBC层多数据源动态切换的核心是使用Spring的AbstractRoutingDataSource构建路由数据源,通过ThreadLocal绑定数据源标识,结合AOP注解实现方法级自动切换,并确保全局仅暴露该路由Bean供其他组件使用。

Java 中在 JDBC 层实现多数据源动态切换,核心不是直接操作 Connection,而是通过 Spring 的 AbstractRoutingDataSource 构建一个“路由型”数据源,让每次 getConnection() 调用自动返回对应库的连接。它不侵入 JDBC 原生 API,而是对 DataSource 接口做一层智能代理。
定义并配置多个真实数据源
先在 application.yml 中声明主从或其他业务库:
spring.datasource.master.url=jdbc:mysql://…/db_masterspring.datasource.slave.url=jdbc:mysql://…/db_slavespring.datasource.report.url=jdbc:postgresql://…/db_report
再用 @ConfigurationProperties 分别创建 masterDataSource()、slaveDataSource() 等 Bean,并确保它们不被 Spring 自动识别为默认数据源(避免冲突)。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
实现路由数据源类
继承 AbstractRoutingDataSource,重写 determineCurrentLookupKey(),从 ThreadLocal 获取当前线程绑定的 key:
- 定义
DataSourceContextHolder工具类:用ThreadLocal<string></string>存当前数据源标识(如"master"、"slave") - 路由类中
determineCurrentLookupKey()直接返回DataSourceContextHolder.getDataSourceType() - 将所有真实数据源(master/slave/report)注入到路由类的
setTargetDataSources()中,并指定一个setDefaultTargetDataSource()
用注解 + AOP 实现方法级自动切换
自定义 @TargetDataSource("slave") 注解,作用于方法或类:
- AOP 切面拦截带该注解的方法,在
@Before中调用DataSourceContextHolder.setDataSourceType(注解值) - 在
@After或@AfterReturning中调用clearDataSourceType(),防止线程复用污染 - 确保切面优先级高于事务管理器(如加
@Order(Ordered.HIGHEST_PRECEDENCE)),避免事务已开启后才切换数据源
保证 JDBC 操作走的是路由数据源
关键一步:整个应用里只暴露这一个 DataSource Bean 给其他组件使用:
- 把路由数据源 Bean 标记为
@Primary - MyBatis 的
SqlSessionFactoryBean、JdbcTemplate 构造器、甚至原生JdbcOperations都必须注入这个路由 Bean,而不是任一真实数据源 - 这样所有通过 Spring 获取的 Connection(包括事务内、DAO 层、模板类)都会经过路由逻辑
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










