手记

Spring多数据源、动态数据源源码解析

在Java中所有的连接池都按照规范实现DataSource接口,在获取连接的时候即可通过getConnection()获取连接而不用关系底层究竟是何数据库连接池。

1 public interface DataSource  extends CommonDataSource, Wrapper {
2
3   Connection getConnection() throws SQLException;
4
5   Connection getConnection(String username, String password) throws SQLException;
6 }
在大多数系统中我们只需要一个数据源,而现在WEB系统通常是Spring为基石。不管你是xml配置,javaBean配置还是yml,properties配置文件配置,其核心就是注入一个数据源交给spring的进行管理。

而在部分系统中我们可能会面临一些情况,连接多个表,主从,甚至多个不同的库等等情况,核心需求就是我们可能需要配置多个连接池。

在mybatis系统中我们使用多数据源可以配置配置多个DataSource,SqlSessionFactory,SqlSessionTemplate,然后在xml和mapper也分开管理。
这种方案在小的系统足够使用,作者认为更适合于多个不同的数据库。

回归正题,在Spring中从2.0.1版本默认提供了AbstractRoutingDataSource,我们继承它实现相关方法,把所有需要的数据源设置进去即可动态的切换数据源。我们可以看下核心方法的源码。

public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {

//设置所有的数据源
private Map<Object, Object> targetDataSources;
//设置默认的数据源,在没有找到相关数据源的时候会返回默认数据源
private Object defaultTargetDataSource;
//快速失败,可忽略
private boolean lenientFallback = true;
//Jndi相关,可忽略
private DataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
//经过解析后的所有数据源,核心
private Map<Object, DataSource> resolvedDataSources;
//经过解析后的默认数据源,核心
private DataSource resolvedDefaultDataSource;

//设置相关参数方法
public void setTargetDataSources(Map<Object, Object> targetDataSources) {
this.targetDataSources = targetDataSources;
}
public void setDefaultTargetDataSource(Object defaultTargetDataSource) {
this.defaultTargetDataSource = defaultTargetDataSource;
}
public void setLenientFallback(boolean lenientFallback) {
this.lenientFallback = lenientFallback;
}
public void setDataSourceLookup(DataSourceLookup dataSourceLookup) {
this.dataSourceLookup = (dataSourceLookup != null ? dataSourceLookup : new JndiDataSourceLookup());}

@Override
br/>}
}

@Override<br <="" a="">public Connection getConnection() throws SQLException {
//核心,获取数据源先查找当前连接池再获取数据源
return determineTargetDataSource().getConnection();}

@Override

//而determineCurrentLookupKey需要我们自己去实现。//通常需要结合Aop和ThreadLocal。我们Aop从注解上获取当前用户用户所希望的数据源,然后设置到当前线程。在determineCurrentLookupKey再从当前线程拿出来返回给determineTargetDataSource由其决定最终数据源protected abstract Object determineCurrentLookupKey();


}

}

@Override

0人推荐
随时随地看视频
慕课网APP