Spring聲明式事務(wù)和@Aspect的攔截順序問題的解決
在使用AbstractRoutingDataSource配置多數(shù)據(jù)源時,發(fā)現(xiàn)使用@aspect配置的DataSourceSwitchAspect總是在聲明式事務(wù)之后執(zhí)行,配置了Order依然不行,經(jīng)過調(diào)研發(fā)現(xiàn)是由于兩者的aop代理方式不一致導(dǎo)致。
在spring內(nèi)部,是通過BeanPostProcessor(《spring 攻略》一書中翻譯為,后處理器)來完成自動創(chuàng)建代理工作的。根據(jù)匹配規(guī)則的不同大致分為三種類別: 1、匹配Bean的名稱自動創(chuàng)建匹配到的Bean的代理,實現(xiàn)類BeanNameAutoProxyCreator 2、根據(jù)Bean中的AspectJ注解自動創(chuàng)建代理,實現(xiàn)類AnnotationAwareAspectJAutoProxyCreator 3、根據(jù)Advisor的匹配機(jī)制自動創(chuàng)建代理,會對容器中所有的Advisor進(jìn)行掃描,自動將這些切面應(yīng)用到匹配的Bean中,實現(xiàn)類DefaultAdvisorAutoProxyCreator
其中@Aspect聲明的aop是通過AnnotationAwareAspectJAutoProxyCreator進(jìn)行代理的,而項目中的聲明式事務(wù)是BeanNameAutoProxyCreator方式進(jìn)行代理的,經(jīng)調(diào)試發(fā)現(xiàn)BeanNameAutoProxyCreator攔截優(yōu)先級高于AnnotationAwareAspectJAutoProxyCreator,order配置只對同一類型的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,由于是通過注解實現(xiàn)的數(shù)據(jù)源切換aop,所以選擇了后者解決方案,如下:
DataSourceConfig
@Bean
public AnnotationAwareAspectJAutoProxyCreator txProxy()
{
/*
* 必須使用AspectJ方式的AutoProxy,這樣才能和DataSourceSwitchAspect保持統(tǒng)一的aop攔截方式,否則不同的攔截方式會導(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)容,希望對大家的學(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ù)幾個常見的問題解決
相關(guān)文章
使用Sharding-JDBC對數(shù)據(jù)進(jìn)行分片處理詳解
這篇文章主要介紹了使用Sharding-JDBC對數(shù)據(jù)進(jìn)行分片處理詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
Spring Security系列教程之會話管理處理會話過期問題
會話過期,是指當(dāng)用戶登錄網(wǎng)站后,較長一段時間沒有與服務(wù)器進(jìn)行交互,將會導(dǎo)致服務(wù)器上的用戶會話數(shù)據(jù)(即session)被銷毀。這篇文章主要介紹了Spring Security系列教程之會話管理處理會話過期問題,需要的朋友可以參考下2021-10-10
SpringSecurity 自定義表單登錄的實現(xiàn)
這篇文章主要介紹了SpringSecurity 自定義表單登錄的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
springboot實現(xiàn)SSE(Server?Sent?Event)的示例代碼
SSE?全稱Server?Sent?Event,直譯一下就是服務(wù)器發(fā)送事件,本文主要為大家詳細(xì)介紹了springboot實現(xiàn)SSE的相關(guān)知識,需要的可以參考一下2024-04-04
關(guān)于swagger配置及踩坑@Api參數(shù)postion無效解決接口排序問題
這篇文章主要介紹了關(guān)于swagger配置及踩坑@Api參數(shù)postion無效解決接口排序問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06

