Spring聲明式事務(wù)和@Aspect的攔截順序問題的解決
在使用AbstractRoutingDataSource配置多數(shù)據(jù)源時(shí),發(fā)現(xiàn)使用@aspect配置的DataSourceSwitchAspect總是在聲明式事務(wù)之后執(zhí)行,配置了Order依然不行,經(jīng)過調(diào)研發(fā)現(xiàn)是由于兩者的aop代理方式不一致導(dǎo)致。
在spring內(nèi)部,是通過BeanPostProcessor(《spring 攻略》一書中翻譯為,后處理器)來完成自動(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是通過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
/** * 數(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
@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,由于是通過注解實(shí)現(xiàn)的數(shù)據(jù)源切換aop,所以選擇了后者解決方案,如下:
DataSourceConfig
@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; }
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- SpringMVC中事務(wù)是否可以加在Controller層的問題
- Spring事務(wù)失效的一種原因關(guān)于this調(diào)用的問題
- JAVA Spring中讓人頭痛的JAVA大事務(wù)問題要如何解決你知道嗎
- 解決Spring或SpringBoot開啟事務(wù)以后無法返回自增主鍵的問題
- 解決try-catch捕獲異常信息后Spring事務(wù)失效的問題
- Spring事務(wù)失效問題分析及解決方案
- SpringBoot內(nèi)部調(diào)用事務(wù)不起作用問題的解決方案
- 詳解Spring Boot微服務(wù)如何集成fescar解決分布式事務(wù)問題
- 解決spring mvc 多數(shù)據(jù)源切換,不支持事務(wù)控制的問題
- Spring中事務(wù)幾個(gè)常見的問題解決
相關(guān)文章
SpringBoot 如何根據(jù)不同profile選擇不同配置
這篇文章主要介紹了SpringBoot 如何根據(jù)不同profile選擇不同配置的操作方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08詳解Java String字符串獲取每一個(gè)字符及常用方法
這篇文章主要介紹了詳解Java String字符串獲取每一個(gè)字符及常用方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Spring?Initializr只能創(chuàng)建為Java?17版本以上的問題解決
這篇文章主要給大家介紹了關(guān)于Spring?Initializr只能創(chuàng)建為Java?17版本以上問題的解決辦法,文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-01-01Java的方法和this關(guān)鍵字如何理解與應(yīng)用
Java語言中的“方法”(Method)在其他語言當(dāng)中也可能被稱為“函數(shù)”(Function)。對(duì)于一些復(fù)雜的代碼邏輯,如果希望重復(fù)使用這些代碼,并且做到“隨時(shí)任意使用”,那么就可以將這些代碼放在一個(gè)大括號(hào){}當(dāng)中,并且起一個(gè)名字。使用代碼的時(shí)候,直接找到名字調(diào)用即可2021-10-10java學(xué)習(xí)指南之字符串與正則表達(dá)式
在日常Java后端開發(fā)過程中,免不了對(duì)數(shù)據(jù)字段的解析,自然就少不了對(duì)字符串的操作,這其中就包含了正則表達(dá)式這一塊的內(nèi)容,下面這篇文章主要給大家介紹了關(guān)于java學(xué)習(xí)指南之字符串與正則表達(dá)式的相關(guān)資料,需要的朋友可以參考下2023-05-05springboot如何查找配置文件路徑的順序和其優(yōu)先級(jí)別
此文是在工作中遇到的關(guān)于springboot配置文件的問題,在網(wǎng)上查閱資料和自己測試之后記錄的,以便日后查閱。希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08