从Spring源码解析事务失效的原因
一、前言
1.Bean是否是代理对象
2.入口函数是否是public的
3.数据库是否支持事务(Mysql的Mvlsam不支持事务),行锁才支持事务
4.切点是否配置正确
5.内部方法间调用导致事务失效
因为this不是代理对象,可以配置 expose-proxy="true",就可以通过AopContext.currentProxy()获取到当前类的代理对象。
<! -- expose-proxy="true”类内部可以获取到当前类的代理对象--><aop: aspectj-autoproxy expose-proxy="true" /> @Enab1eAspect3AutoProxy(exposeProxy = true)
也可以注入当前bean
6.异常类型是否配置正确
默认只支持RuntimeException和Error,不支持检查异常
想要支持检查异常需要配置rollbackFor
@Transactional(rollbackFor = Exception.class)
7.异常被catch住了
代码中手动catch了异常,然后又未抛出来,此时事务就不生效了。
二、方法不是 public 的
以下来自Spring官方文档

大概意思就是 @Transactional 只能用于 public 的方法上,否则事务不会失效,如果要用在非 public 方法上,可以开启 AspectJ 代理模式。

TransactionInterceptor#invoke

TransactionAspectSupport#invokeWithinTransaction

AbstractFallbackTransactionAttributeSource#getTransactionAttribute

AbstractFallbackTransactionAttributeSource#computeTransactionAttribute

allowPublicMethodsOnly方法由子类AnnotationTransactionAttributeSource实现,该子类方法中默认是true,所以当你加了事务注解的方法不是public时,该方法直接返回null
以上只说明 在spring的事务管理中存在这样一个 public的判断,至于后边为啥由于这个判断导致没有织入事务,并没有说明;
public导致失效原因
三、内部方法间调用导致事务失效

因为spring声明式事务是基于AOP实现的,是使用动态代理来达到事务管理的目的,当前类调用的方法上面加@Transactional 这个是没有任何作用的,因为调用这个方法的是this,没有经过 Spring 的代理类。
解决方案一:
再声明一个service,自己注入自己,将内部调用改为外部调用

解决方案二:







解决方案三:
使用编程式事务

四、异常类型是否配置正确
抛出RuntimeException异常,事务生效
抛出Exception异常,事务不生效




我们看下TransactionInterceptor类
TransactionInterceptor#invoke

TransactionAspectSupport#invokeWithinTransaction

TransactionAspectSupport#completeTransactionAfterThrowing



配置了这个,Exception异常的事务,就会生效

五、异常被catch住
代码中手动catch了异常,然后又未抛出来,此时事务就不生效了。
解决方法:要么不catch需要回滚的异常,要么catch之后再抛出,要么手动回滚

解决方案一:
catch之后往外抛异常

解决方案二:
catch之后,设置手动回滚

到此这篇关于从Spring源码解析事务失效的原因的文章就介绍到这了,更多相关Spring事务失效内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
IDEA中使用jclasslib插件可视化方式查看类字节码的过程详解
查看JAVA字节码有两种方式一种是使用 jdk命令 javap,还有一种就是 使用 插件了,今天给大家分享IDEA中使用jclasslib插件可视化方式查看类字节码的过程详解,感兴趣的朋友跟随小编一起看看吧2021-05-05
结合mybatis-plus实现简单不需要写sql的多表查询
这篇文章主要给大家介绍了关于结合mybatis-plus实现简单不需要写sql的多表查询的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用mybatis-plus具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧2019-09-09
springboot启动报错:application startup failed问题
这篇文章主要介绍了springboot启动报错:application startup failed问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-07-07
SpringBoot2如何集成Elasticsearch6.x(TransportClient方式)
这篇文章主要介绍了SpringBoot2如何集成Elasticsearch6.x(TransportClient方式)问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-05-05
Java RandomAccessFile 指定位置实现文件读取与写入
这篇文章主要介绍了Java RandomAccessFile 指定位置实现文件读取与写入的相关资料,需要的朋友可以参考下2017-01-01
jdk中动态代理异常处理分析:UndeclaredThrowableException
最近在工作中遇到了报UndeclaredThrowableException的错误,通过查找相关的资料,终于解决了,所以这篇文章主要给大家介绍了关于jdk中动态代理异常处理分析:UndeclaredThrowableException的相关资料,需要的朋友可以参考下2018-04-04


最新评论