Spring AbstractRoutingDataSource

AbstractRoutingDataSource抽象类,可以实现动态切换数据库。

抽象方法

重写此方法传入查找查找键 lookupKey

protected abstract Object determineCurrentLookupKey();

成员变量及set方法

  • 数据源map,value为DataSource实例或数据源名称String
private Map<Object, Object> targetDataSources;

public void setTargetDataSources(Map<Object, Object> targetDataSources) {
	this.targetDataSources = targetDataSources;
}
  • 默认数据源,DataSource实例或数据源名称String
@Nullable
private Object defaultTargetDataSource;

public void setDefaultTargetDataSource(Object defaultTargetDataSource) {
	this.defaultTargetDataSource = defaultTargetDataSource;
}
  • 当指定的lookupKey在targetDataSources中不存在时是否使用默认数据源,默认为ture使用默认数据源
@Nullable
private boolean lenientFallback = true;

public void setLenientFallback(boolean lenientFallback) {
	this.lenientFallback = lenientFallback;
}
  • 数据源查找,通过提供的数据源名称获取数据源实例
private DataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
public void setDataSourceLookup(@Nullable DataSourceLookup dataSourceLookup) {
	this.dataSourceLookup = (dataSourceLookup != null ? dataSourceLookup : new JndiDataSourceLookup());
}
  • 已解析的数据源,value为DataSource实例
@Nullable
private Map<Object, DataSource> resolvedDataSources;
  • 已解析的默认数据源
@Nullable
private DataSource resolvedDefaultDataSource;

方法

  • 初始化方法,解析数据源
@Override
public void afterPropertiesSet() {
	if (this.targetDataSources == null) {
		throw new IllegalArgumentException("Property 'targetDataSources' is required");
	}
	// 解析提供的targetDataSources, 通过resolveSpecifiedDataSource方法将value转换为DataSource类型
	this.resolvedDataSources = CollectionUtils.newHashMap(this.targetDataSources.size());
	this.targetDataSources.forEach((key, value) -> {
		Object lookupKey = resolveSpecifiedLookupKey(key);
		DataSource dataSource = resolveSpecifiedDataSource(value);
		this.resolvedDataSources.put(lookupKey, dataSource);
	});
	// 解析默认数据源,转换为DataSource类型
	if (this.defaultTargetDataSource != null) {
		this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource);
	}
}
  • 解析查找建,默认原样返回
protected Object resolveSpecifiedLookupKey(Object lookupKey) {
	return lookupKey;
}
  • 将数据源对象解析为数据源实例
protected DataSource resolveSpecifiedDataSource(Object dataSource) throws IllegalArgumentException {
	// 可以强转
	if (dataSource instanceof DataSource) {
		return (DataSource) dataSource;
	}
	// dataSource为数据源名称,通过dataSourceLookup获取DataSource实例
	else if (dataSource instanceof String) {
		return this.dataSourceLookup.getDataSource((String) dataSource);
	}
	else {
		throw new IllegalArgumentException(
				"Illegal data source value - only [javax.sql.DataSource] and String supported: " + dataSource);
	}
}

  • 连接数据库方法
// 调用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);
}
  • 通过lookupKey获取当前数据源
protected DataSource determineTargetDataSource() {
	Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
	Object lookupKey = determineCurrentLookupKey();
	DataSource dataSource = this.resolvedDataSources.get(lookupKey);
	// 未通过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;
}

参考

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值