【原】继承AbstractRoutingDataSource再通过AOP实现动态数据源切换
? 關(guān)于A(yíng)bstractRoutingDataSource動(dòng)態(tài)切換數(shù)據(jù)源是我在研究某開(kāi)源項(xiàng)目時(shí)候才注意到的,大概就看懂了Spring AOP切面這里,根據(jù)作者的意思是通過(guò)繼承這個(gè)抽象類(lèi)可以實(shí)現(xiàn)數(shù)據(jù)源的動(dòng)態(tài)切換,也就是Controller調(diào)用Service的時(shí)候會(huì)切換數(shù)據(jù)源。最終研究了一天也沒(méi)發(fā)現(xiàn)什么結(jié)果,第二天便嘗試查看源碼和查看相關(guān)資料,試圖揭開(kāi)這個(gè)疑惑
- ?? 首先貼上源代碼如下:
#以上是核心代碼,我疑惑的地方在于A(yíng)bstractRoutingDataSource這里,剛開(kāi)始去看的時(shí)候不明白為什么繼承這個(gè)就能實(shí)現(xiàn)數(shù)據(jù)源切換,最后進(jìn)入AbstractRoutingDataSource.class去查看究竟,發(fā)現(xiàn)繼承了一個(gè)AbstractDataSource的抽象類(lèi),這里我突然有點(diǎn)明白AbstractRoutingDataSource的意思,一個(gè)路由數(shù)據(jù)源,一般用到Routing的地方都可以進(jìn)行動(dòng)態(tài)配置。
-
大致翻譯一下源碼作者對(duì)這個(gè)類(lèi)的說(shuō)明:調(diào)用一個(gè)基于各種目標(biāo)數(shù)據(jù)源。
????? 繼續(xù)往下看又看到幾個(gè)重要信息
???
???? 上圖發(fā)現(xiàn)2個(gè)方法分別是setTargetDataSources(注入目標(biāo)數(shù)據(jù)源)?和setDefaultTargetDataSource(注入默認(rèn)的數(shù)據(jù)源);然后想到是否可以通過(guò)Spring 配置來(lái)注入這2個(gè)方法,帶著這個(gè)思緒繼續(xù)接著繼續(xù)往下看;然后又看到比較重要的信息如下:
?上圖發(fā)現(xiàn)有g(shù)etConnection方法,jdbc獲取連接的方法,而當(dāng)我點(diǎn)進(jìn)determineTargetDataSource方法時(shí)得到了一個(gè)確切答案,代碼如下:
? 上圖大致的意思是會(huì)調(diào)用determineCurrentLookupKey這個(gè)抽象方法獲取數(shù)據(jù)源,如果是null則獲取默認(rèn)的數(shù)據(jù)源,反之則是獲取我們注入的數(shù)據(jù)源, 這樣就實(shí)現(xiàn)了數(shù)據(jù)源的動(dòng)態(tài)切換, 這時(shí)候我通過(guò)斷點(diǎn)啟動(dòng)也驗(yàn)證了這一個(gè)流程確實(shí)如此。
?
?
?? 分析了一個(gè)動(dòng)態(tài)切換流程后,那么問(wèn)題來(lái)了,如何讓我們的代碼實(shí)現(xiàn)這個(gè)功能呢?其實(shí)就是重寫(xiě)AbstractRoutingDataSource方法后再通過(guò)aop動(dòng)態(tài)切換數(shù)據(jù)源,那么如何知道切換條件是什么?這時(shí)候可以根據(jù)Service層的方法來(lái)確定,一般我們Service都是會(huì)以find,add,delete,update 開(kāi)頭; 例如發(fā)現(xiàn)是find,get開(kāi)頭則走讀庫(kù),delete,update則走寫(xiě)庫(kù)。
?
? #分析完后把spring配置文件貼上來(lái)
<bean id="dataSource" class="com.zdd.data.aspect.ChooseDataSource" lazy-init="true"><description>數(shù)據(jù)源</description><property name="targetDataSources"><map key-type="java.lang.String" value-type="javax.sql.DataSource"><!-- write --><entry key="write" value-ref="writedataSource" /><!-- read --><entry key="read" value-ref="readdataSource" /></map></property><!-- 設(shè)置默認(rèn)的目標(biāo)數(shù)據(jù)源為讀 --><property name="defaultTargetDataSource" ref="readdataSource" /><property name="methodType"><map key-type="java.lang.String"><!-- read --><entry key="read" value=",get,,find,select,count,list,query," /><!-- write --><entry key="write" value=",add,insert,create,update,delete,remove," /></map></property></bean>? ?#上面的配置大概流程是先指定2個(gè)數(shù)據(jù)源注入targetDataSources,然后配置一組數(shù)組用來(lái)存放判斷走讀庫(kù)還是寫(xiě)庫(kù)的條件,如果是read那么肯定是把read注入的數(shù)據(jù)源拿出來(lái),如果是write則把write的數(shù)據(jù)源取出來(lái)。
?
更新時(shí)間-----------------------------------------------2018年5月16日 13:54:27------------------------------------------------------------
? ?#但是這時(shí)候會(huì)有一個(gè)奇怪的現(xiàn)象就是每次調(diào)用的時(shí)候會(huì)走chooseDataSource再走AOP,經(jīng)查詢(xún)發(fā)現(xiàn)是事務(wù)問(wèn)題導(dǎo)致,因?yàn)樗茸吡耸聞?wù)切面,然后事務(wù)還沒(méi)結(jié)束的時(shí)候如果再去切換數(shù)據(jù)源的話(huà)是不成立的。方法解決很簡(jiǎn)單,設(shè)置一下切換數(shù)據(jù)源的AOP的優(yōu)先級(jí),確保在事務(wù)執(zhí)行之前就已經(jīng)切換數(shù)據(jù)源,如下圖:
?
轉(zhuǎn)載于:https://www.cnblogs.com/zdd-java/p/zdd_datasource_aop.html
總結(jié)
以上是生活随笔為你收集整理的【原】继承AbstractRoutingDataSource再通过AOP实现动态数据源切换的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 怎么查看一个网站是用什么语言编写的?
- 下一篇: C语言第三次博客作业---单层循环结构