在使用abstractroutingdatasource配置多數(shù)據(jù)源時(shí),發(fā)現(xiàn)使用@aspect配置的datasourceswitchaspect總是在聲明式事務(wù)之后執(zhí)行,配置了order依然不行,經(jīng)過(guò)調(diào)研發(fā)現(xiàn)是由于兩者的aop代理方式不一致導(dǎo)致。
在spring內(nèi)部,是通過(guò)beanpostprocessor(《spring 攻略》一書(shū)中翻譯為,后處理器)來(lái)完成自動(dòng)創(chuàng)建代理工作的。根據(jù)匹配規(guī)則的不同大致分為三種類別: 1、匹配bean的名稱自動(dòng)創(chuàng)建匹配到的bean的代理,實(shí)現(xiàn)類beannameautoproxycreator 2、根據(jù)bean中的aspectj注解自動(dòng)創(chuàng)建代理,實(shí)現(xiàn)類annotationawareaspectjautoproxycreator 3、根據(jù)advisor的匹配機(jī)制自動(dòng)創(chuàng)建代理,會(huì)對(duì)容器中所有的advisor進(jìn)行掃描,自動(dòng)將這些切面應(yīng)用到匹配的bean中,實(shí)現(xiàn)類defaultadvisorautoproxycreator
其中@aspect聲明的aop是通過(guò)annotationawareaspectjautoproxycreator進(jìn)行代理的,而項(xiàng)目中的聲明式事務(wù)是beannameautoproxycreator方式進(jìn)行代理的,經(jīng)調(diào)試發(fā)現(xiàn)beannameautoproxycreator攔截優(yōu)先級(jí)高于annotationawareaspectjautoproxycreator,order配置只對(duì)同一類型的aop攔截方式起作用,如下:
datasourceswitchaspect
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
/** * 數(shù)據(jù)源切換切面 * @author matchstick */ @aspect @order ( 1 ) //確保該切面在transaction之前執(zhí)行 @component public class datasourceswitchaspect { private logger logger = loggerfactory.getlogger(getclass()); @pointcut ( "@annotation(com.etu.multidatasource.test.datasource.datasourceid)" ) public void pointcut(){} @before ( "@annotation(datasourceid)" ) public void switchdatasource(joinpoint point, datasourceid datasourceid) { string dsid = datasourceid.value(); multidatasourcecontextholder.setdatasourceid(dsid); logger.debug( "switch datasource -> {}" , dsid); } @after ( "@annotation(datasourceid)" ) public void restoredatasource(joinpoint point, datasourceid datasourceid) { multidatasourcecontextholder.removedatasourceid(); logger.debug( "restore datasource -> {}" , multidatasourcecontextholder.getdefaultdatasourceid()); } } |
datasourceconfig
1
2
3
4
5
6
7
8
9
10
|
@bean public beannameautoproxycreator txproxy() { beannameautoproxycreator creator = new beannameautoproxycreator(); creator.setinterceptornames( "txadvice" ); creator.setbeannames( "*service" , "*serviceimpl" ); creator.setproxytargetclass( true ); creator.setorder( 2 ); return creator; } |
解決方案:要么修改datasourceswitchaspect的aop方式為beannameautoproxycreator,要么修改事務(wù)aop方式為annotationawareaspectjautoproxycreator,由于是通過(guò)注解實(shí)現(xiàn)的數(shù)據(jù)源切換aop,所以選擇了后者解決方案,如下:
datasourceconfig
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@bean public annotationawareaspectjautoproxycreator txproxy() { /* * 必須使用aspectj方式的autoproxy,這樣才能和datasourceswitchaspect保持統(tǒng)一的aop攔截方式,否則不同的攔截方式會(huì)導(dǎo)致order失效 */ annotationawareaspectjautoproxycreator c = new annotationawareaspectjautoproxycreator(); c.setinterceptornames( "txadvice" ); c.setincludepatterns(arrays.aslist( "execution (public com.etu..*service(..))" )); c.setproxytargetclass( true ); c.setorder( 2 ); return c; } |
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://my.oschina.net/u/2333620/blog/1805869