分析动态代理给 Spring 事务埋下的坑

Posted ImportNew

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分析动态代理给 Spring 事务埋下的坑相关的知识,希望对你有一定的参考价值。

(给ImportNew加星标,提高Java技能)

www.jianshu.com/p/0da29e4f354a


前言


Spring的声明式事务让我们不在编写获得连接、关闭连接、开启事务、提交事务、回滚事务等代码,通过一个简单的@Transactional注解,就让我们轻松进行事务处理。我们知道Spring事务基于AOP,采用动态代理实现,虽然使用简单,但是在实际场景中,我们也会遇到一些坑。而往往遇到坑之后,我们都会茫然,这是由于没有对Spring事务的实现机制做一点了解导致的。因此本篇博客将从原理的角度分析下动态代理给Spring事务埋下的坑!


从动态代理到Spring事务


UserService:


UserService接口


txMethod和txMethod2方法模拟事务方法(相当于@Transactional)


 noTxMethod方法是普通方法


UserServiceImpl:


分析动态代理给 Spring 事务埋下的坑

UserServiceImpl


在Spring事务中,我们往往是在Service层进行事务控制。  


我们在UserServiceImpl中想模拟的是:


一个有事务的方法,去调用另一个有事务的方法,会怎么样?


一个没有事务的方法,去调用一个有事务的方法,会怎么样?


UserHandler:


分析动态代理给 Spring 事务埋下的坑

UserHandler


这里为了简便,通过方法名称来判断是否开启事务。


显然,txMethod方法、txMethod2方法都“应该”开启事务。


UserTest:


分析动态代理给 Spring 事务埋下的坑

UserTest


下面,我们来说下运行结果



proxyInstance.txMethod2()方法,会开启事务,这没有问题。


proxyInstance.txMethod()方法,虽然在事务方法txMethod()内部调用了txMethod2()事务方法,但是并没有新开启事务。


proxyInstance.noTxMethod()方法,虽然在没有事务的方法noTxMethod()内部调用了有事务的txMethod2()方法,但是并没有开启事务。


下面让我们来对应下Spring事务中的现象:


Spring事务


上述的情况,说白了,就是在一个Service内部,事务方法之间的嵌套调用,普通方法和事务方法之间的嵌套调用,都不会开启新的事务!


 为什么会这样呢? 


其实通过上面的动态代理的代码,你应该可以发现:


动态代理最终都是要调用原始对象的,而原始对象在去调用方法时,是不会再触发代理了!


那么如何解决呢?


很简单,我们完全可以在抽出一个XxxService,在其内部调用UserService.txMethod()和UserService.txMethod2()方法即可。总而言之,避免在一个Service内部进行事务方法的嵌套调用!(因为动态代理导致这种场景事务失效了。


好像Spring事务如此简单,但是背后却有这些道道,你被坑过么?


推荐阅读

(点击标题可跳转阅读)





看完本文有收获?请转发分享给更多人

关注「ImportNew」,提升Java技能

好文章,我在看❤️

以上是关于分析动态代理给 Spring 事务埋下的坑的主要内容,如果未能解决你的问题,请参考以下文章

Spring事务注意事项 以及 遇到的坑

Spring事务常见的坑

Spring两种动态代理原理分析+AOP的坑

Spring 从入门到精通系列 09——转账方法的事务问题与动态代理

设计模式之代理模式详解和应用

Spring声明式事务的实现方式选择(JDK动态代理与cglib)