AbstractRoutingDataSource详解,分析多数据源切换原理

39 篇文章 1 订阅
16 篇文章 0 订阅

在spring中有一个抽象类AbstractRoutingDataSource类,通过这个类可以实现动态数据源切换。如下是这个类的成员变量

// 是存储将要切换的多数据源bean信息,一般是<beanName,DataSource-bean>
private Map<Object, Object> targetDataSources;
private Object defaultTargetDataSource;
private Map<Object, DataSource> resolvedDataSources;

在其afterPropertiesSet方法中。

@Override
public void afterPropertiesSet() {
	if (this.targetDataSources == null) {
		throw new IllegalArgumentException("Property 'targetDataSources' is required");
	}
	this.resolvedDataSources = new HashMap<Object, DataSource> (this.targetDataSources.size()); //初始化resolvedDataSources 
    // 1. 循环原有存储多数据源bean信息的targetDataSources
	for (Map.Entry<Object, Object> entry : this.targetDataSources.entrySet()) {
        // 2. 判断lookUpKey要不要重写,一般都是beanName,不用重写
		Object lookupKey = resolveSpecifiedLookupKey(entry.getKey());
        // 3. 判断value是否Datasource对象,不是则生成DataSource对象,一般都是
		DataSource dataSource = resolveSpecifiedDataSource(entry.getValue());
        // 4. 将魔改的<BeanName,DataSource> 存入resolvedDataSources中备用
		this.resolvedDataSources.put(lookupKey, dataSource);
	}
        //如果默认数据源不为空则指定对应数据源
	if (this.defaultTargetDataSource != null) {
		this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource);
	}
}

连接数据库的getConnection()方法,调用的是determineTargetDataSource()方法,来创建连接。

@Override
public Connection getConnection() throws SQLException {
	return determineTargetDataSource().getConnection();
}
 
@Override
public Connection getConnection(String username, String password) throws SQLException {
	return determineTargetDataSource().getConnection(username, password);
}

而determineTargetDataSource()方法是决定spring容器连接那个数据源。

而选择哪个数据源又是由determineCurrentLookupKey()方法来决定的,此方法是抽象方法,需要我们继承AbstractRoutingDataSource抽象类来重写此方法。该方法返回一个key,该key是bean中的beanName,并赋值给lookupKey,由此key可以通过resolvedDataSources属性的键来获取对应的DataSource值,从而达到数据源切换的功能。

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;
}

  • 11
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当使用Spring框架时,可以通过`AbstractRoutingDataSource`来实现多数据源切换。下面是一个简单的Java示例代码: 首先,创建一个继承自`AbstractRoutingDataSource`的自定义数据源类: ```java import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class CustomRoutingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { // 返回当前线程所使用的数据源的标识符 return DbContextHolder.getDataSource(); } } ``` 接下来,创建一个用于存储当前线程使用的数据源的上下文类: ```java public class DbContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); public static void setDataSource(String dataSourceName) { contextHolder.set(dataSourceName); } public static String getDataSource() { return contextHolder.get(); } public static void clearDataSource() { contextHolder.remove(); } } ``` 然后,在Spring的配置文件中配置多个数据源和`CustomRoutingDataSource`: ```xml <bean id="dataSource1" class="org.apache.commons.dbcp2.BasicDataSource"> <!-- 配置第一个数据源的相关属性 --> </bean> <bean id="dataSource2" class="org.apache.commons.dbcp2.BasicDataSource"> <!-- 配置第二个数据源的相关属性 --> </bean> <bean id="customRoutingDataSource" class="com.example.CustomRoutingDataSource"> <property name="targetDataSources"> <map> <entry key="dataSource1" value-ref="dataSource1"/> <entry key="dataSource2" value-ref="dataSource2"/> </map> </property> <property name="defaultTargetDataSource" ref="dataSource1"/> </bean> ``` 最后,在需要切换数据源的地方,调用`DbContextHolder.setDataSource()`方法来设置当前线程使用的数据源,例如: ```java // 切换dataSource1 DbContextHolder.setDataSource("dataSource1"); // 执行数据库操作 // 切换dataSource2 DbContextHolder.setDataSource("dataSource2"); // 执行数据库操作 ``` 这样,通过`AbstractRoutingDataSource`和`DbContextHolder`配合使用,就可以实现多数据源切换

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值