1. 程式人生 > >Spring(AbstractRoutingDataSource)實現動態資料來源切換

Spring(AbstractRoutingDataSource)實現動態資料來源切換

    

wKioL1TxHqHQ_2EIAAA2t2DPtbc761.jpg

    單個數據源繫結給sessionFactory,再在Dao層操作,若多個數據源的話,那不是就成了下圖:

    wKioL1TxH1-yOkTCAAB1EzUwMXo661.jpg

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

wKioL1TxIC-gAVlAAABpRIiqH-w927.jpg

 

二、實現原理

    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,如果找不到,就用配置預