翻看之前springboot集成的mybatis讀寫分離,發現還有些疏漏 ,有的還不甚理解,於是翻看下源碼;
讀寫分離 主要就是數據路由的時候重寫roundRobinDataSouceProxy方法 ,roundRobinDataSouceProxy中最重要的是 AbstractRoutingDataSource類中的一個抽象方法determineCurrentLookupKey()
下面我們來看下AbstractRoutingDataSource類
/**
* 把所有數據庫都放在路由中
* @return
*/
@Bean(name="roundRobinDataSouceProxy")
public AbstractRoutingDataSource roundRobinDataSouceProxy() {
Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
//把所有數據庫都放在targetDataSources中,注意key值要和determineCurrentLookupKey()中代碼寫的一至,
//否則切換數據源時找不到正確的數據源
targetDataSources.put(DataSourceType.write.getType(), writeDataSource);
targetDataSources.put(DataSourceType.read.getType(), readDataSource);
//路由類,尋找對應的數據源
AbstractRoutingDataSource proxy = new AbstractRoutingDataSource(){
@Override
protected Object determineCurrentLookupKey() {
return null;
}
};
proxy.setDefaultTargetDataSource(writeDataSource);//默認庫
////設置數據源映射
proxy.setTargetDataSources(targetDataSources);
return proxy;
}
AbstractRoutingDataSource源碼
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean{
public Connection getConnection() throws SQLException {
return this.determineTargetDataSource().getConnection();
}
protected DataSource determineTargetDataSource() {
Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
//引用抽象方法
Object lookupKey = this.determineCurrentLookupKey();
DataSource 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 + "]");
} else {
return dataSource;
}
}
protected abstract Object determineCurrentLookupKey();
AbstractRoutingDataSource源碼中有個Object lookupKey = this.determineCurrentLookupKey();
在spring源碼中很常見的引用 抽象類中的方法引用抽象方法的實現;
最核心的就determineCurrentLookupKey方法實現, 返回一個datasource實例枚舉key,然後當前resolvedDataSources中獲取key對應的數據源,從而完成,數據源的動態切換。