多數據源切換詳細講解及其原理


myBatis多數據源連接

1、首先得有一個Springmvc + Spring + Mybatis  maven項目

2、編輯一個擴展AbstractRoutingDataSource類,DynamicDataSource.java重寫determineCurrentLookupKey()方法。

 

3 封裝一個的對數據源進行操作的類,DbContextUtils.java

 

使用ThreadLocal維護變量時,ThreadLocal為每個使用該變量的線程提供獨立的變量副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。

從線程的角度看,目標變量就象是線程的本地變量,這也是類名中Local”所要表達的意思。

ThreadLocal的接口方法

ThreadLocal類接口很簡單,只有4個方法,我們先來了解一下:

① void set(Object value)設置當前線程的線程局部變量的值。

② public Object get()該方法返回當前線程所對應的線程局部變量。

③ public void remove()將當前線程局部變量的值刪除,目的是為了減少內存的占用,該方法是JDK 5.0新增的方法。需要指出的是,當線程結束后,對應該線程的局部變量將自動被垃圾回收,所以顯式調用該方法清除線程的局部變量並不是必須的操作,但它可以加快內存回收的速度。

④ protected Object initialValue()返回該線程局部變量的初始值,該方法是一個protected的方法,顯然是為了讓子類覆蓋而設計的。這個方法是一個延遲調用方法,在線程第1次調用get()set(Object)時才執行,並且僅執行1次。ThreadLocal中的缺省實現直接返回一個null

4應用spring aop來設置,把配置的數據源類型都設置成為注解標簽,在service層中需要切換數據源的方法上,寫上注解標簽,調用相應方法切換數據源.

4.1編輯注解標簽TargetDataSource.java

 

注解說明

RetentionPolicy.RUNTIME —— 這種類型的Annotations將被JVM保留,所以他們能在運行時被JVM或其他使用反射機制的代碼所讀取和使用

Documented 注解表明這個注解應該被 javadoc工具記錄. 默認情況下,javadoc是不包括注解的. 但如果聲明注解時指定了 @Documented,則它會被 javadoc 之類的工具處理, 所以注解類型信息也會被包括在生成的文檔中

@Target說明了Annotation所修飾的對象范圍:Annotation可被用於 packagestypes(類、接口、枚舉、Annotation類型)、類型成員(方法、構造方法、成員變量、枚舉值)、方法參數和本地變量(如循環變量、catch參數)。在Annotation類型的聲明中使用了target可更加明晰其修飾的目標

4.2編輯切面的BeanAspectTargetDataSource.java

 

@Pointcut("@annotation(com.tynet.service.TargetDataSource)")

攔截帶有@TargetDataSource注解的方法

@Before(value="setTargetDataSource() && @annotation(dataSource)")

前置任務中dataSource 指的是自定義切面注解上所附帶的參數

 

5、配置配置文件

 

 

 

我這只顯示兩個,實際上可以連接很多數據源,只需要增加bean然后把id加入map中,我的默認的數據庫是db_plat

6、記得聲明自動為spring容器中那些配置@aspectJ切面的bean創建代理,織入切面。

 

7、方法上加上注解即可使用

 

8、實現原理

擴展SpringAbstractRoutingDataSource抽象類。

該類充當了DataSource的路由中介, 能有在運行時, 根據某種key值來動態切換到真正的DataSource上。

AbstractRoutingDataSource的源碼:

 

它繼承了AbstractDataSource,而AbstractDataSource正是javax.sql.DataSource的子類。

 

Java中數據庫有很多連接方式,在眾多方式中除了JDBC外都有DataSource對象。

DataSource可以看作數據源,它封裝了數據庫參數,連接數據庫,程序中操作DataSource對象即可對數據庫進行增刪改查操作。

分析下AbstractRoutingDataSource實現DataSourcegetConnection方法:

 

看來重點是determineTargetDataSource()方法,上源碼:

 

看注解,檢索當前目標的數據源。

重點在於determineCurrentLookupKey()方法。

 

 

 

 

 

 

 

可以看到如果當前線程變量沒有值,它首先被初始化為默認的值。

determineCurrentLookupKey()AbstractRoutingDataSource類中的一個抽象方法,而它的返回值是當前線程要用的數據源dataSourcekey值,有了這個key值,resolvedDataSource(這是個map,由配置文件中設置好后存入的)就從中取出對應的DataSource,如果找不到,就用配置默認的數據源。

而我們上面的所有操作都是要擴展AbstractRoutingDataSource類,並重寫其中的determineCurrentLookupKey()方法,來實現數據源的切換。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM