1.使用
1)写一个DynamicDataSource类继承AbstractRoutingDataSource
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DSNameHolder.getDSName(); } /** * used for test * @return */ public DataSource getCurrentDataSource() { return super.determineTargetDataSource(); } }
2) DSNameHolder
public class DSNameHolder { public static ThreadLocal<String> DS_NAME_HOLDER = new ThreadLocal<String>(); public static void setDSName(String dsName) { DS_NAME_HOLDER.set(dsName); } public static String getDSName() { return DS_NAME_HOLDER.get(); } }
3)测试
spring-ds.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean name="datasource" class="com.siyuan.study.spring.jdbc.DynamicDataSource"> <property name="targetDataSources"> <map> <entry key="ds_a" value-ref="datasource_a"/> <entry key="ds_b" value-ref="datasource_b"/> </map> </property> <property name="defaultTargetDataSource" ref="datasource_a"/> </bean> <bean id="datasource_a" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="jdbc:mysql://localhost:3306;databaseName=test_a" /> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="username" value="root" /> <property name="password" value="123456" /> </bean> <bean id="datasource_b" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="jdbc:mysql://localhost:3306;databaseName=test_b" /> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="username" value="root" /> <property name="password" value="123456" /> </bean> </beans>
DynamicDataSourceTest
public class DynamicDataSourceTest { private ApplicationContext ctxt; @Before public void setup() { ctxt = new ClassPathXmlApplicationContext("spring-ds.xml"); } @Test public void getConnection() { DynamicDataSource datasource = (DynamicDataSource) ctxt.getBean("datasource"); DataSource datasource_a = (DataSource) ctxt.getBean("datasource_a"); DataSource datasource_b = (DataSource) ctxt.getBean("datasource_b"); assertSame(datasource_a, datasource.getCurrentDataSource()); //switch to ds_b DSNameHolder.setDSName("ds_b"); assertSame(datasource_b, datasource.getCurrentDataSource()); //switch to ds_a DSNameHolder.setDSName("ds_a"); assertSame(datasource_a, datasource.getCurrentDataSource()); } }
2.源码分析
1)afterPropertiesSet
public void afterPropertiesSet() { if (this.targetDataSources == null) { throw new IllegalArgumentException("Property 'targetDataSources' is required"); } this.resolvedDataSources = new HashMap<Object, DataSource>(this.targetDataSources.size()); for (Map.Entry entry : this.targetDataSources.entrySet()) { Object lookupKey = resolveSpecifiedLookupKey(entry.getKey()); DataSource dataSource = resolveSpecifiedDataSource(entry.getValue()); this.resolvedDataSources.put(lookupKey, dataSource); } if (this.defaultTargetDataSource != null) { this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource); } }
2)getConnection
public Connection getConnection() throws SQLException { return determineTargetDataSource().getConnection(); } public Connection getConnection(String username, String password) throws SQLException { return determineTargetDataSource().getConnection(username, password); }
3)determineTargetDataSource
protected DataSource determineTargetDataSource() { Assert.notNull(this.resolvedDataSources, "DataSource router not initialized"); Object lookupKey = determineCurrentLookupKey(); DataSource dataSource = this.resolvedDataSources.get(lookupKey); if (dataSource == null && (this.lenientFallback || lookupKey == null)) { dataSource = this.resolvedDefaultDataSource; } if (dataSource == null) { throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]"); } return dataSource; }
3.参考资料
http://blog.163.com/wang_hj138@126/blog/static/140800106201263151242338/
http://www.360doc.com/content/13/1016/15/14212114_321868950.shtml
相关推荐
springboot+mybatis+mysql+AbstractRoutingDataSource实现多数据源切换(一写多读数据源)项目中包含完整的demo案例配备文档说明,亲测可用;实现简单,代码思路清晰.
SpringBoot2.x 继承 AbstractRoutingDataSource 动态数据源切换实现 JPA读写分离。 使用MyCat代理MySQL8数据库,添加root账户(读写)和user账户(只读)模拟读写简单分离。
本篇文章主要介绍了详解Spring(AbstractRoutingDataSource)实现动态数据源切换,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
`ThreadLocal` 是 Java 中的一个类,用于存储线程局部变量。线程局部变量与普通的变量不同,它不是共享的,每个线程...结合 `ThreadLocal` 和 `AbstractRoutingDataSource`,我们可以轻松地在运行时动态地切换数据源。
主要介绍了使用Spring的AbstractRoutingDataSource实现多数据源切换示例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
spring+druid+AtomikosDataSource实现多数据源切换及分布式事务控制
本篇文章主要介绍了详解利用Spring的AbstractRoutingDataSource解决多数据源的问题。具有一定的参考价值,有兴趣的可以了解一下。
MySQL Master Slave 集群构架和spring整合,里面实现的是动态切换数据源,大家都是知道,spring2之后添加AbstractRoutingDataSource这个东西,这个就可以实现切换数据源,实现思路是:先按照搭建MySQL的MasterSlave...
使用注解配置实现Spring动态数据源切换,实现原理 1、自定义动态数据源类DynamicDataSource: 实现spring类AbstractRoutingDataSource的方法determineCurrentLookupKey 2、自定义Spring AOP类DataSourceAspect 3、...
Spring Boot整合Mybatis使用druid实现多数据源自动切换
基于Spring的 AbstractRoutingDataSource 进行简单的封装,方便进行数据源的切换,目前主要用于主从数据库的读写切换上。切换spring数据源的工具,使用aop注解方式进行快速切换,减少编码的入侵
主从数据源切换(两个版本)一是利用Spring提供的AbstractRoutingDataSource,二是使用自定义数据源切换类 模块 actdemo ├── mybatisGenerator --mybatis生成程序 └── web --SpringBoot项目 集成activiti6.0.0...
《在Sping Cloud(Spring Boot)中基于AbstractRoutingDataSource 实现多数据源动态切换》多数据源元数据存储表,在postgres数据库可直接运行,如果是别的数据库请自行修改sql语句
(1)、AbstractRoutingDataSource注册多数据源,AOP实现读写分离、读写源自动切换 (2)、一主多从,多个从库的负载均衡策略可以自定义。(双主多从、故障转移因mysql环境为一主一从,所以代码未实现,不难实现,...
spring +springboot+mybatis+maven 读写分离,数据库采用mysql, 采用springboot 采用项目框架搭建,继承spring 中的AbstractRoutingDataSource,实现 determineCurrentLookupKey 进行数据源的动态切换,采用Spring ...
Spring boot + Mybatis + alibaba druid通过继承AbstractRoutingDataSource的determineCurrentLookupKey来动态切换DataSource,主从切换,读写分离。 可以直接运行,完整工程代码 + SQL脚本。
--利用AbstractRoutingDataSource实现动态数据源切换 --> 数据源 <!-- write --> <!-- read --> <!-- 从org.springframework.jdbc.datasource.lookup....