1. 程式人生 > >詳解AbstractRoutingDataSource(動態資料來源切換)實現原理(轉載)

詳解AbstractRoutingDataSource(動態資料來源切換)實現原理(轉載)

轉載地址:詳解AbstractRoutingDataSource(動態資料來源切換)實現原理


多資料來源讓人最頭痛的,不是配置多個數據源,而是如何能靈活動態的切換資料來源。例如在一個springhibernate的框架的專案中,我們在spring配置中往往是配置一個dataSource來連線資料庫,然後繫結給sessionFactory,在dao層程式碼中再指定sessionFactory來進行資料庫操作。
在這裡插入圖片描述


上圖是單資料來源dataSource結構。但是上圖的缺點太明顯了,不支援多個數據源,於是我們再改進一下,讓它支援多資料來源。

這種結構實現了多資料來源,但是缺點也很明顯啊,具有多個SessionFactory

不具有靈活性,而且太笨重了。如果再加一個數據源,就需要再加一個SessionFactory


SessionFactory介面負責初始化Hibernate。它充當資料儲存源的代理,並負責建立Session物件。這裡用到了工廠模式。需要注意的是SessionFactory並不是輕量級的。

顧名思義,SessionFactory,就是用來建立session會話(具體接下來講)的工廠。如果存在多個Sessionfactory 那麼Session是不是就亂套了,因此這種架構不可取。那麼下面這種架構就應用而生。

詳解AbstractRoutingDataSource(動態資料來源切換)實現原理

看看上圖,是不是感覺合理了很多。SpringAbstractRoutingDataSource

就是採用這種架構。


看到這裡你應該就明白了 AbstractRoutingDataSource 的原理。如果你還不明白,沒關係,我們接著往下看。

看看?AbstractRoutingDataSource 的設計原始碼吧!

public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {
……
}

擴充套件Spring的AbstractRoutingDataSource抽象類(該類充當了DataSource的路由中介, 能有在執行時, 根據某種key值來動態切換到真正的DataSource

上。)

從上可以看出它繼承了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類中的一個抽象方法,而它的返回值是你所要用的資料來源dataSourcekey值,有了這個key值,resolvedDataSource(這是個map,由配置檔案中設定好後存入的)就從中取出對應的DataSource,如果找不到,就用配置預設的資料來源。

看完原始碼,應該有點啟發了吧,沒錯!你要擴充套件AbstractRoutingDataSource類,並重寫其中的determineCurrentLookupKey方法,來實現資料來源的切換:

 import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; 
 /**  
  * 獲取資料來源(依賴於spring)  
  * @author linhy  
  */ 
 public class DynamicDataSource extends AbstractRoutingDataSource{     
 
 @Override
 protected Object determineCurrentLookupKey() {         
 	return DataSourceHolder.getDataSource();     
 	} 
 }
 

參考