Spring事務失敗場景(一) ——AOP切面順序導致事務不能正確回滾


AOP切面順序導致事務不能正確回滾

原因:事務切面的優先級最低,自定義的切面默認跟事務優先級相同,並且自定義切面在內層,若這是自定義切面沒有正確拋出異常,則導致外層事務不能正常回滾

@Transactional(rollbackFor = Exception.class)
public void transfer(int from, int to, int amount) throws FileNotFoundException {
    int cash = accountMapper.findBalance(from);
    if(cash - amount >= 0) {
        accountMapper.update(form, -1* aomunt);
        new FileInputStream("aaa");
        account.update(to, amount);
    }
}

@Component
@Aspect
class MyAspect {
    @Around("execution(* transfer(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        //獲取連接點所在的對象,前置通知
        LoggerUitls.get().debug("log:{}", jointPoint.getTarget());
        
        try {
            return joinPoint.proceed();		//切入點方法執行
        }catch(Throable e) {
            e.printStackTrace();  //異常通知
            return null; 
        }finally {
            System.out.println("最終通知");
        }
    }
}

事務的執行:

  • Transaction切面
  • MyAspect切面
  • 業務代碼
  • MyAspect切面: 異常沒有拋出,導致事務沒有執行
  • Transaction切面

解決方案:

  • 自定義切面內正確拋出異常:即事務正確回滾
    • throw new RuntimeException();
    • TranscationInterceptor.currentTransactionStatus().setRollbackOnly();
  • 讓自定義切面進程先執行,即事務切面運行在自定義切面內
@Component
@Aspect
@Order(Ordered.LOWEST_PRECEDENCE -1)  //越小,優先級越高
class MyAspect {
    @Around("execution(* transfer(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        LoggerUitls.get().debug("log:{}", jointPoint.getTarget());
     
        try {
            return joinPoint.proceed();		
        }catch(Throable e) {
            throw new RuntimeException();
            //或 TranscationInterceptor.currentTransactionStatus().setRollbackOnly();
            return null; 
        }finally {
            System.out.println("最終通知");
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM