天天看點

java 動态切換資料源方式_Spring(AbstractRoutingDataSource)實作動态資料源切換

java 動态切換資料源方式_Spring(AbstractRoutingDataSource)實作動态資料源切換

單個資料源綁定給sessionFactory,再在Dao層操作,若多個資料源的話,那不是就成了下圖:

java 動态切換資料源方式_Spring(AbstractRoutingDataSource)實作動态資料源切換

可見,sessionFactory都寫死在了Dao層,若我再添加個資料源的話,則又得添加一個sessionFactory。是以比較好的做法應該是下圖:

java 動态切換資料源方式_Spring(AbstractRoutingDataSource)實作動态資料源切換

二、實作原理

1、擴充Spring的AbstractRoutingDataSource抽象類(該類充當了DataSource的路由中介, 能有在運作時, 根據某種key值來動态切換到真正的DataSource上。)

從AbstractRoutingDataSource的源碼中:

public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean

我們可以看到,它繼承了AbstractDataSource,而AbstractDataSource不就是javax.sql.DataSource的子類,So我們可以分析下它的getConnection方法:

public Connection getConnection() throws SQLException {

return determineTargetDataSource().getConnection();

}

public Connection getConnection(String username, String password) throws SQLException {

return determineTargetDataSource().getConnection(username, password);

}

擷取連接配接的方法中,重點是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;

}

上面這段源碼的重點在于determineCurrentLookupKey()方法,這是AbstractRoutingDataSource類中的一個抽象方法,而它的傳回值是你所要用的資料源dataSource的key值,有了這個key值,resolvedDataSource(這是個map,由配置檔案中設定好後存入的)就從中取出對應的DataSource,如果找不到,就用配置預設的資料源。