美文网首页
JDK动态代理给Spring事务埋下的坑

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

作者: TheLights | 来源:发表于2018-03-16 11:09 被阅读314次

service


image

模拟动态代理事务


image

测试类


image

预测结果
模拟事务:开启事务
execute doLink
模拟事务:关闭事务
模拟事务:开启事务
execute doPick
模拟事务:关闭事务
execute unDo

实际结果
模拟事务:开启事务
execute doLink
模拟事务:关闭事务
模拟事务:开启事务
execute doPick
模拟事务:关闭事务
execute unDo

结果一致,运行正常

我们修改service和测试类
修改后的service(在事务方法中调用事务方法,在非事务方法中调用事务方法)


图片.png

修改后的测试类


image

预测结果
模拟事务:开启事务
execute doLink
模拟事务:开启事务
execute doPick
模拟事务:关闭事务
模拟事务:关闭事务
execute unDo
模拟事务:开启事务
execute doPick
模拟事务:关闭事务

测试结果
模拟事务:开启事务
execute doLink
execute doPick
模拟事务:关闭事务
execute unDo
execute doPick
结果不一致,doLink方法里调用doPick没有触发事务,unDo方法里调用doPick也没有触发事务

分析问题的本质
我们知道Spring事务管理是通过JDK动态代理的方式进行实现的(另一种是使用CGLib动态代理实现的),也正是因为动态代理的特性造成了上述doLink方法调用doPick方法的时候造成了doPick方法中的事务失效!简单的来说就是doLink方法调用doPick方法的时候doPick方法的事务是不起作用的,此时的doPick方法像一个没有加事务的普通方法。那么动态代理的这个特性到底是什么才会造成Spring事务失效?这是因为在Java中doLink方法中调用doPick方法,本质上就相当于把doPick方法的方法体放入到doLink方法中,也就是内部方法,同样的不管你嵌套了多少层,只有调用代理对象的方法才会触发事务。

如何解决这个坑
1.使用代理对象去调用方法
2.再加一层XXXService分别去调用doLink方法和doPick方法(没修改前的代码在控制器层分别调用doLink方法和doPick方法)

针对方案一对代码改版
修改后的service


image

修改后的测试类


image

预测结果
模拟事务:开启事务
execute doLink
模拟事务:开启事务
execute doPick
模拟事务:关闭事务
模拟事务:关闭事务
execute unDo
模拟事务:开启事务
execute doPick
模拟事务:关闭事务

测试结果
模拟事务:开启事务
execute doLink
模拟事务:开启事务
execute doPick
模拟事务:关闭事务
模拟事务:关闭事务
execute unDo
模拟事务:开启事务
execute doPick
模拟事务:关闭事务

结果一致,解决问题

相关文章

网友评论

      本文标题:JDK动态代理给Spring事务埋下的坑

      本文链接:https://www.haomeiwen.com/subject/qcslqftx.html