spring aop和事务同时开启带来的一些问题

本文探讨了Spring AOP环绕通知与事务管理同时使用时出现的问题。由于作者在切面中手动捕获并记录异常,导致事务无法感知异常而正常提交。分析指出,切面的高优先级可能导致事务管理失效。尽管不会生成两个代理对象,但Spring会按优先级嵌套执行通知。建议在解决问题后理解其根本原因。
最近自己在写一个aop切面,主要是用来记录日志和打印一些信息的,在测试过程中,发现,业务方法在加了事务之后,如果有其他异常抛出,事务并没有回滚,于是,就Google了一把,发现有大佬遇到过这个问题,大部分博客给到的答案是:因为切面的优先级低于事务的优先级,导致事务advisor生成的代理对象被,切面生成的代理对象给覆盖了,需要在切面上加上@Order(1)注解,这样可以保证,切面的优先级较高
我自己忽然间想到之前,遇到过类似的问题,并且也记录到了线上问题模块,按照实际操作之后,确实:在切面上加了@Order(1)注解之后,事务就生效了
但是自己又想了下,之前学习spring源码的时候,并不记得会生成两个代理对象。。。所以这里就很好奇,所以,自己又撸了一遍aop的源码,最后发现原因了,我的结论是这样的:
  1. 因为我自己写的切面,在@Aroud环绕通知的方法,我手动加了try catch 捕获了throwable 然后打印了一行日志
  2. 在没有加@Order(1)的时候,确实是事务先执行,然后再执行aop的切面,但是在执行切面的时候,捕获到了数组越界的异常,然后打印了日志,没有继续上抛异常
  3. 继而导致事务在处理的时候,并没有捕获到异常,直接就提交事务了, 如果用一段伪代码来描述的话,那应该是这样的

try{
try{
执行目标方法
}catch(th){
log.error(“执行报错”)
}
}catch (Throwable ex) {
// target invocation exception
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}

那么问题,就来了,按照我的这个代码,只有在切面中,记录了error日志之后,然后继续抛出异常就可以了,我自己试了下,不在切面上添加@Order(1)注解,也确实是ok的
所以,我写的这个代码,同时开启aop和事务不生效,是因为切面优先级高,先执行,但是把异常给吞掉了,导致事务不知道发生了异常

aop和事务源码

抛开这个问题,那到底会不会生成两个代理对象?我认为是不会生成两个代理对象的,因为我觉得,对于spring来讲,一个bean,既要开启事务,又有切面,如果生成两个代理对象,其实是没必要的,既然切面和事务有优先级,那就嵌套就ok了

在之前博客中,有介绍过springaop和事务的源码,其实,简单来说

  1. 在bean初始化流程中,依次会解析aop的切面和事务advisor
  2. 第八个后置处理器执行的时候,会获取到作用在当前bean的advisor(事务其实就是一个advisor)
  3. 假如此时获取到有两个advisor作用在该bean上,那就根据这两个advisor生成代理对象,在生成代理对象的时候,会专门有一个变量来存储所有的advisor
  4. 在目标方法被执行的时候,会获取方法所要执行的通知方法,按照优先级嵌套执行

所以,我觉得,对于一个问题,要有自己的思考,在解决了问题之后,需要确认下,真正的原因是什么

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值