2019独角兽企业重金招聘Python工程师标准>>>

【问题】

Spring的声明式事务,我想就不用多介绍了吧,一句话“自从用了Spring AOP啊,事务管理真轻松啊,真轻松;事务管理代码没有了,脑不酸了,手不痛了,一口气全配上了事务;轻量级,测试起来也简单,嘿!”。不管从哪个角度看,轻量级声明式事务都是一件解放生产力的大好事。所以,我们“一直用它”。

不过,最近的一个项目里,却碰到了一个事务管理上的问题:有一个服务类,其一个声明了事务的方法,里面做了三次插入SQL操作,但是在后面出错回滚时,却发现前面插入成功了,也是说,这个声明了事务的方法,实际上并没有真正启动事务!怎么回事呢?难道Spring的声明式事务失效了?

【分析】

这个问题,表面上是事务声明失效的问题,实质上很可能是Spring的AOP机制实现角度的问题。我想到很久以前研究Spring的AOP实现时发现的一个现象:对于以Cglib方式增强的AOP目标类,会创建两个对象,一个事Bean实例本身,一个是Cglib增强代理对象,而不仅仅是只有后者。

我们知道,Spring的AOP实现方式有两种:1、Java代理方式;2、Cglib动态增强方式,这两种方式在Spring中是可以无缝自由切换的。Java代理方式的优点是不依赖第三方jar包,缺点是不能代理类,只能代理接口。

Spring通过AopProxy接口,抽象了这两种实现,实现了一致的AOP方式:

现在看来,这种抽象同样带了一个缺陷,那就是抹杀了Cglib能够直接创建普通类的增强子类的能力,Spring相当于把Cglib动态生成的子类,当普通的代理类了,这也是为什么会创建两个对象的原因。下图显示了Spring的AOP代理类的实际调用过程:

因此,从上面的分析可以看出,methodB没有被AopProxy通知到,导致最终结果是:被Spring的AOP增强的类,在同一个类的内部方法调用时,其被调用方法上的增强通知将不起作用。

而这种结果,会造成什么影响呢:

1:内部调用时,被调用方法的事务声明将不起作用

2:换句话说,你在某个方法上声明它需要事务的时候,如果这个类还有其他开发者,你将不能保证这个方法真的会在事务环境中

3:再换句话说,Spring的事务传播策略在内部方法调用时将不起作用。不管你希望某个方法需要单独事务,是RequiresNew,还是要嵌套事务,要Nested,等等,统统不起作用。

4:不仅仅是事务通知,所有你自己利用Spring实现的AOP通知,都会受到同样限制。。。。

【解难】

问题的原因已经找到,其实,我理想中的AOP实现,应该是下面这样:

使用代理

1、Proxy.insertAAA() 代理对象加了事物,这样就可以增强事物。

public void a() {  aopProxy.b();//即调用AOP代理对象的b方法即可执行事务切面进行事务增强  }  

判断一个Bean是否是AOP代理对象可以使用如下三种方法:

AopUtils.isAopProxy(bean)        : 是否是代理对象;

AopUtils.isCglibProxy(bean)       : 是否是CGLIB方式的代理对象;

AopUtils.isJdkDynamicProxy(bean) : 是否是JDK动态代理方式的代理对象;

  1. <aop:aspectj-autoproxy expose-proxy="true"/><!—注解风格支持-->
  2. <aop:config expose-proxy="true"><!—xml风格支持-->

修改我们的代码

this.b();-----------修改为--------->((AService) AopContext.currentProxy()).b();

在使用的过程中,提示错误:

关于AOP无法切入同类调用方法的问题,给方式使用注解

@Transactional(propagation = Propagation.REQUIRED,
    isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class)

文章参考:

https://blog.csdn.net/dapinxiaohuo/article/details/52092447

https://blog.csdn.net/aya19880214/article/details/50640596

转载于:https://my.oschina.net/maojindaoGG/blog/1920783

【每日提高之声明式事物】spring声明式事务 同一类内方法调用事务失效相关推荐

  1. spring声明式事务 同一类内方法调用事务失效

    一 宏观说明 [问题] Spring的声明式事务,我想就不用多介绍了吧,一句话"自从用了Spring AOP啊,事务管理真轻松啊,真轻松:事务管理代码没有了,脑不酸了,手不痛了,一口气全配上 ...

  2. Spring事务内方法调用自身事务

    Spring事务内方法调用自身事务 增强的三种方式 ServiceA.java文件: 查看Spring Tx的相关日志: 可以看到只创建了一个事物ServiceA.service方法的事务,但是cal ...

  3. spring同类方法调用事务使用说明

    2019独角兽企业重金招聘Python工程师标准>>> #spring声明式事务使用说明: #前提: 1.springboot 2.0.3.RELEASE 2.application ...

  4. Spring事务—方法调用事务回滚

    转自:https://blog.csdn.net/m0_38027656/article/details/84190949 写这篇文章的初衷呢就是最近遇到了一个spring事务的大坑.与其说是坑,还不 ...

  5. Spring中同一个类中方法调用事务不生效,非事务方法调用事务方式事务不生效

    我们假定在SerivceXXX中有两个方法: serviceA 非事务方法 serviceB事务方法 如果serviceA中方法定义类似如下: public void serviceA(){..... ...

  6. springboot 调用方法事物_SpringBoot 内部方法调用,事务不起作用的原因及解决办法...

    在做业务开发时,遇到了一个事务不起作用的问题.大概流程是这样的,方法内部的定时任务调用了一个带事务的方法,失败后事务没有回滚.查阅资料后,问题得到解决,记录下来分享给大家. 场景 我在这里模拟一个场景 ...

  7. 框架源码专题:Spring声明式事务Transactional的原理

    文章目录 1. @Transactional的使用 2. spring事务的原理 2.1 开启事务,注册bean的后置处理器和相关bean对象,封装Advisor 2.2 匹配并创建动态代理 2.3 ...

  8. Spring声明式事务管理实现及原理详解

    目录 1.实现步骤 1.1.配置事务管理器 1.2.启动事务注解 1.3.业务添加注解 2.代码演示 2.1.bean文件 2.2.目标类 2.3.测试类 3.Spring事务属性 3.1.传播行为 ...

  9. Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法

    Spring 事务机制回顾 Spring事务一个被讹传很广说法是:一个事务方法不应该调用另一个事务方法,否则将产生两个事务.  结果造成开发人员在设计事务方法时束手束脚,生怕一不小心就踩到地雷.    ...

最新文章

  1. ipad无法与itunes同步,提示因为这台电脑不再被授权使用在此ipad上购买的项目解决方案...
  2. step1 . day10 C语言基础练习之指针和函数
  3. linux系统中/etc/syslog.conf文件解读
  4. mac上的更新node npm
  5. php添加项目,thinkphp添加一个项目
  6. oracle bcp out,SQL Server利用bcp命令把SQL语句结果生成文本文件
  7. 【汇编语言】王爽 - 内中断复习
  8. Android Studio下载
  9. 和 8 个程序员聊了一下午,集齐了这些经验!
  10. 【刷算法】LeetCode- 阶乘后的零
  11. (转)美国证监会SEC发布调查报告,认定ICO为证券投资邀约
  12. 数据库课程设计(在线销售系统)
  13. 神经网络的多任务学习概览
  14. 专访卜茂霞:嵌入式汽车开发潜力巨大
  15. 笔记:Smith圆图及其计算
  16. 蜗牛学院:项目管理十大TION法
  17. 【环境配置】使用 docker 制作一个ubuntu16.04 + ROS + pytorch-gpu 的镜像
  18. 软件测试_笔记大全(完整版)
  19. 【算法】Java 中栈的使用
  20. java获取当前年月日历_获取当前月日历

热门文章

  1. 一个简单粗暴的爬虫 - 必应今日美图
  2. BZOJ 1691: [Usaco2007 Dec]挑剔的美食家( 平衡树 )
  3. document.querySelector和querySelectorAll方法
  4. Struts2零配置 Zero Config+CodeBehind
  5. J2ME开发心得-数组的使用
  6. poj1509最小表示法
  7. hdu4971 流-最大权闭包
  8. hdu2870暴力或者dp优化
  9. hdu4756 最小树+树形dp
  10. 【Linux 内核 内存管理】RCU 机制 ④ ( RCU 模式下更新链表项 list_replace_rcu 函数 | 链表操作时使用 smp_wmb() 函数保证代码执行顺序 )