在使用abstractroutingdatasource配置多數據源時,發現使用@aspect配置的datasourceswitchaspect總是在聲明式事務之后執行,配置了order依然不行,經過調研發現是由于兩者的aop代理方式不一致導致。
在spring內部,是通過beanpostprocessor(《spring 攻略》一書中翻譯為,后處理器)來完成自動創建代理工作的。根據匹配規則的不同大致分為三種類別: 1、匹配bean的名稱自動創建匹配到的bean的代理,實現類beannameautoproxycreator 2、根據bean中的aspectj注解自動創建代理,實現類annotationawareaspectjautoproxycreator 3、根據advisor的匹配機制自動創建代理,會對容器中所有的advisor進行掃描,自動將這些切面應用到匹配的bean中,實現類defaultadvisorautoproxycreator
其中@aspect聲明的aop是通過annotationawareaspectjautoproxycreator進行代理的,而項目中的聲明式事務是beannameautoproxycreator方式進行代理的,經調試發現beannameautoproxycreator攔截優先級高于annotationawareaspectjautoproxycreator,order配置只對同一類型的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
|
/** * 數據源切換切面 * @author matchstick */ @aspect @order ( 1 ) //確保該切面在transaction之前執行 @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,要么修改事務aop方式為annotationawareaspectjautoproxycreator,由于是通過注解實現的數據源切換aop,所以選擇了后者解決方案,如下:
datasourceconfig
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@bean public annotationawareaspectjautoproxycreator txproxy() { /* * 必須使用aspectj方式的autoproxy,這樣才能和datasourceswitchaspect保持統一的aop攔截方式,否則不同的攔截方式會導致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; } |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://my.oschina.net/u/2333620/blog/1805869