排坑之旅——动态代理给Spring事务种下的坑

前言

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


从动态代理到Spring事务

UserService:架构

UserService接口

txMethod和txMethod2方法模拟事务方法(至关于@Transactional)并发

noTxMethod方法是普通方法分布式

UserServiceImpl:高并发

UserServiceImpl

在Spring事务中,咱们每每是在Service层进行事务控制。性能

咱们在UserServiceImpl中想模拟的是:学习

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

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

UserHandler:orm

UserHandler

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

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

UserTest:

UserTest

下面,咱们来讲下运行结果:

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

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

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

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

Spring事务

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

为何会这样呢?

其实经过上面的动态代理的代码,你应该能够发现:

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

那么如何解决呢?

很简单,咱们彻底能够在抽出一个XxxService,在其内部调用UserService.txMethod()和UserService.txMethod2()方法便可。总而言之,避免在一个Service内部进行事务方法的嵌套调用!(由于动态代理致使这种场景事务失效了。)


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


欢迎工做一到五年的Java工程师朋友们加入Java架构开发:878249276

群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用本身每一分每一秒的时间来学习提高本身,不要再用"没有时间“来掩饰本身思想上的懒惰!趁年轻,使劲拼,给将来的本身一个交代!

相关文章
相关标签/搜索