Spring(AbstractRoutingDataSource)實現動態資料來源切換
阿新 • • 發佈:2019-04-11
單個數據源繫結給sessionFactory,再在Dao層操作,若多個數據源的話,那不是就成了下圖:
可見,sessionFactory都寫死在了Dao層,若我再添加個資料來源的話,則又得新增一個sessionFactory。所以比較好的做法應該是下圖:
二、實現原理
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()方法,看原始碼:
/** * Retrieve the current target DataSource. Determines the * {@link #determineCurrentLookupKey() current lookup key}, performs * a lookup in the {@link #setTargetDataSources targetDataSources} map, * falls back to the specified * {@link #setDefaultTargetDataSource default target DataSource} if necessary. * @see #determineCurrentLookupKey() */ 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,如果找不到,就用配置預