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()方法,看源碼:

    /** 
     * 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,如果找不到,就用配置默認的數據源。
2、看完源碼,應該有點啓發了吧,沒錯!你要擴展AbstractRoutingDataSource類,並重寫其中的determineCurrentLookupKey()方法,來實現數據源的切換:

package com.datasource.test.util.database;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * 獲取數據源(依賴於spring)
 * @author linhy
 */
public class DynamicDataSource extends AbstractRoutingDataSource{
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceHolder.getDataSource();
    }
}

DataSourceHolder這個類則是我們自己封裝的對數據源進行操作的類:

package com.datasource.test.util.database;

/**
 * 數據源操作
 * @author linhy
 */
public class DataSourceHolder {
    //線程本地環境
    private static final ThreadLocal<String> dataSources = new ThreadLocal<String>();
    //設置數據源
    public static void setDataSource(String customerType) {
        dataSources.set(customerType);
    }
    //獲取數據源
    public static String getDataSource() {
        return (String) dataSources.get();
    }
    //清除數據源
    public static void clearDataSource() {
        dataSources.remove();
    }

}
發佈了51 篇原創文章 · 獲贊 30 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章