这篇笔记主要记录spring事务失效场景三:在同一个类中,用非事务方法调用事务方法
首先,这种场景,失效的原因是,在非事务方法中,调用同一个类的事务方法,和动态代理没有关系,事务拦截器无法拦截到,就是一个this方法调用。所以,在实际业务开发过程中,一定要避免这种场景

应用

应用其实简单,就是这样的,在非事务方法中,调用了同类中的一个事务方法

下面这里是debug的结果

可以看到,在进行调用的时候,完全没有被事务拦截器所拦截到,是因为非事务方法testNoTrans(),所以,这里就是一个普通的方法的调用,导致这样的原因是:在cglibAopProxy在拦截到目标方法之后,会根据method,判断当前method所要经过的通知方法有哪些,但是非事务方法,所需要执行的通知方法是空,所以,就直接进行了目标方法的调用,也就是说
1.如果在A.class类中的某些方法,添加了事务注解,那spring是会为该类生成代理对象的
2.在调用该类中的非事务方法的时候,也是会被代理对象所拦截,只是说,如果当前方法所需要执行的通知方法是空,就直接去调用目标方法了
3.如果调用的方法是事务方法,则会被事务拦截器所拦截到,去进行事务的处理

不生效的原理

org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;Object target = null;TargetSource targetSource = this.advised.getTargetSource();try {/*** 这里和exposeProxy这个属性设置有关系,如果在@EnableTransactionManagemenr* 注解中设置了exposeProxy属性为true,这里就会设置到threadLocal中一个proxy对象* 在业务代码中,就可以通过AopContext.getCurrentProxy()获取到一个代理对象*/if (this.advised.exposeProxy) {// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null);/*** 获取目标方法执行时,需要调用的通知方法,然后将对应的advice转换为拦截器放到chain中* 如果chain为空,就直接调用目标方法,否则就通过aop的形式,调用所有的通知方法*/List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);Object retVal;// Check whether we only have one InvokerInterceptor: that is,// no real advice, but just reflective invocation of the target.if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {// We can skip creating a MethodInvocation: just invoke the target directly.// Note that the final invoker must be an InvokerInterceptor, so we know// it does nothing but a reflective operation on the target, and no hot// swapping or fancy proxying.Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = methodProxy.invoke(target, argsToUse);}else {// We need to create a method invocation.../*** 这里采用的是责任链模式*/retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}retVal = processReturnType(proxy, target, method, retVal);return retVal;}finally {if (target != null && !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}}
}

这里的源码,可以看到,在根据方法获取到所有要执行的通知方法之后,会进行一层判断,如果要执行的通知方法为空,就直接调用目标方法

所以,getInterceptorsAndDynamicInterceptionAdvice是核心方法,会根据当前method,去判断当前method所需要经过的通知方法,前面也说过,动态代理对象是针对类的,只要一个类中有添加事务注解,那就会为其生成代理对象,但是在实际调用的时候,会根据method,进行一层判断,只有加了事务注解的方法,才会被拦截器拦截到
如果在非事务方法中,调用事务方法,其实就是一个普通方法的调用,并不会被拦截器拦截到

spring事务失效场景三:内部方法调用相关推荐

  1. Spring事务失效场景

    1.Spring事务最终依赖的数据库的事务,如果用的是mysql的话,执行引擎要是innodb;因为只有innoDB 支持事务. 2.Spring的事务是原理是aop,所以加事务所在bean是要Spr ...

  2. 8个Spring事务失效的场景,你碰到过几种?

    前言 作为Java开发工程师,相信大家对Spring种事务的使用并不陌生.但是你可能只是停留在基础的使用层面上,在遇到一些比较特殊的场景,事务可能没有生效,直接在生产上暴露了,这可能就会导致比较严重的 ...

  3. Spring事务失效 -方法内部调用

    首先感谢网友的文章 Spring事务失效的2种情况 JDK动态代理给Spring事务埋下的坑 前提知识: 两个前提 1 注解使用 spring容器的事务管理注解 @org.springframewor ...

  4. 详解spring事务失效和回滚失败的场景

    详解spring事务失效和回滚失败的场景 详解spring事务失效和回滚失败的场景 前言 一 .事务不生效 1.访问权限问题 2. 方法用final修饰 3.方法的内部调用 3.1 新加一个Servi ...

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

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

  6. 详细整理Spring事务失效的具体场景及解决方案

    实际项目开发中,如果涉及到多张表操作时,为了保证业务数据的一致性,大家一般都会采用事务机制:好多小伙伴可能只是简单了解一下,遇到事务失效的情况,便会无从下手,溪源此篇文章给大家整理了一下常见Sprin ...

  7. 面试官:Spring事务失效的场景有哪些?如何解决?

     作者:溪~源 blog.csdn.net/xuan_lu/article/details/107797505 实际项目开发中,如果涉及到多张表操作时,为了保证业务数据的一致性,大家一般都会采用事务机 ...

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

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

  9. spring同一个类中,一个方法调用另外一个注解(@Transactional)方法时,注解失效

    title: "spring同一个类中,一个方法调用另外一个注解(@Transactional)方法时,注解失效" url: "https://wsk1103.githu ...

  10. Redis事务失效的三种场景

    文章目录 Redis 事务失效的三种场景 命令入队报错 命令执行报错 乐观锁导致失效 Redis 事务失效的三种场景 Redis事务失败,有三种类型的失败场景: 命令入队报错 在事务提交之前,客户端执 ...

最新文章

  1. 89. a^b【快速幂模板】
  2. 阿里云马劲:保证云产品持续拥有稳定性的实践和思考\n
  3. 最短路径问题----Dijkstra算法的解释
  4. OpenGL之macOS上的环境搭建
  5. RabbitMQ 普通集群配置_04
  6. jrebel 远程部署 配置记录
  7. 也谈莫言荣获诺贝尔文学奖后我的“低调”
  8. ECMAScript面向对象(一)
  9. IntelliJ IDEA、Kotlin、PyCharm 背后公司 JetBrains 遭美国调查!
  10. CodeChef June Challenge 2017
  11. 《Android进阶指北》— Android 书籍
  12. 【Oracle】Oracle通过表名查询触发器
  13. 二建 机电工程常用材料及工程设备
  14. for i in range()使用方法
  15. 如何共享计算机网络,电脑怎么共享网络给手机上网
  16. 宝塔绑定域名访问不了_千字长文教你使用 宝塔面板 快速搭建网站
  17. 什么是pptp,什么是vps?两者有何区别?
  18. jQuery事件 笔记
  19. 第三章 part2 单调性与极值
  20. 梦饮酒者,旦而哭泣;梦哭泣者,旦而田猎。方其梦也,不知其梦也。 ------庄子.齐物论-节选

热门文章

  1. 神经结构化学习 4 图像分类的对抗性学习Adversarial learning for image classification
  2. 容器技术Docker K8s 44 Serverless Kubernetes(ASK)详解-ASK弹性伸缩管理
  3. 算法:Number of Islands(岛屿的个数)
  4. must be str,not int
  5. Ubuntu 16.04安装Docker
  6. module 'bit' not found:No LuaRocks module found for bit
  7. 1*1的卷积核与Inception
  8. 【生信进阶练习1000days】day9-BSgenome和AnnotationHub
  9. Neural Style Transfer
  10. Ten graph questions of about 2000 difficulty of Codeforces Round 2