淺談Spring+Mybatis的數據源動態切換

這個問題困擾我好幾天,今天稍微總結一下,以後還得繼續 deep dig。不過,今天長沙的陽光真的是甚好啊!

首先,說說這個數據源切換的使用情景:因爲項目用到了多個數據源的數據,有時候得切換一下數據源,去另外一個數據源下獲取數據。

 

 那麼代碼到底要怎麼寫呢?

自定義一個類去繼承AbstractRoutingDataSource類並重寫其determineCurrentLookupKey()方法

先直接貼我項目中的代碼:

一:首先是spring中的數據源配置:

數據源的實現類是 DynamicDataSource ,等下會介紹

 然後是兩個數據源的配置 :dictdataSource 和defaultdataSource

 二:DynamicDataSource 

package com.zhiguangyun.modules.empi.util;


/**
 * 實現數據庫的動態切換
 */
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource{

	@Override
	protected Object determineCurrentLookupKey() {
		return getDataSourceType();
	}
  
	private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
	/**
	 * @Description: 設置數據源類型
	 * @param dataSourceType  數據庫類型
	 * @return void
	 * @throws
	 */
	public static void setDataSourceType(String dataSourceType) {
		contextHolder.set(dataSourceType);
	}
	
	/**
	 * @Description: 獲取數據源類型
	 * @param 
	 * @return String
	 * @throws
	 */
	public static String getDataSourceType() {
		return contextHolder.get();
	}
	
	/**
	 * @Description: 清除數據源類型
	 * @param 
	 * @return void
	 * @throws
	 */
	public static void clearDataSourceType() {
		contextHolder.remove();
	}
	

}

關鍵代碼:

三.調用切換數據源的代碼

 

以上就是我項目中實現數據源切換的代碼,然後就聊一下這個流程。

首先   DynamicDataSource 繼承了AbstractRoutingDataSource 類, 並實現其抽象方法determineCurrentLookupKey()

 AbstractRoutingDataSource 繼承了 AbstractDataSource類 並且實現了 InitializingBean接口

那麼InitializingBean 接口又有什麼屬性呢?

InitializingBean接口爲bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是實現該接口的類,在初始化bean的時候都會執行該方法。這個afterPropertiesSet  方法 甚至 先於 init-method 方法執行。那麼當在spring配置中數據源初始化的時候,它就會去調用 afterPropertiesSet 方法。

這是AbstractRoutingDataSource 類中,重寫的afterPropertiesSet()方法

從上面可以看到,它將 我們在 spring中配置的 兩個數據源的信息存入了 resolveDataSources這個map中,回顧一下先前代碼:

(1)AbstractRoutingDataSource 的屬性  

(2)spring 中的數據源配置

 spring 的配置中是將 默認數據源信息存到了 key值爲 defaultTargetDataSource 的map中,而要切換的數據源信息存到了key值爲 targetDataSources 的map中,這和AbstractRoutingDataSource類中的屬性是對應的。當spring 初始化 完bean的屬性後,就會調用afterPropertiesSet這個方法,然後將 數據源的信息又存到了 resolveDataSources 這個map中,方便後面根據key從這個map中拿dataSource。

Mybatis只有在真正執行sql操作的時候纔會去獲取數據庫連接。我們看下DataSource中 Connection getConnection() throws SQLException;是如何實現的:

關鍵在於 determineTargetDataSource()方法中用到了 determineCurrentLookupKey()方法,而determineCurrentLookupKey()是一個抽象方法,要子類是實現。其實這裏,就是數據源切換的核心代碼了,因爲這裏返回一個你要切換的數據源去connection。

Object lookupKey = determineCurrentLookupKey();determineCurrentLookupKey()方法是我們DynamicDataSource類實現的。

切換數據源的時候,首先將要切換的那個數據源的名字  通過 setDataSource中,也就是存到ThreadLocal中。然後  determineCurrentLookupKey 再去獲取ThreadLocal中保存的 key 值。拿到了這個要切換的key(也就是那個數據源的名字)之後, 再從afterPropertiesSet()中存儲好了的resolvedDataSources這個map中獲得key對應的dataSource,再返回給  Connection getConnection()去進行數據源的連接。

這就是整個數據源切換的流程。

其實 ,由於基礎不是很好,對於這個流程,我自己還有些地方比較困惑,希望看到我這篇博客的朋友,可以指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章