spring事务失效场景三:内部方法调用
这篇笔记主要记录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事务失效场景三:内部方法调用相关推荐
- Spring事务失效场景
1.Spring事务最终依赖的数据库的事务,如果用的是mysql的话,执行引擎要是innodb;因为只有innoDB 支持事务. 2.Spring的事务是原理是aop,所以加事务所在bean是要Spr ...
- 8个Spring事务失效的场景,你碰到过几种?
前言 作为Java开发工程师,相信大家对Spring种事务的使用并不陌生.但是你可能只是停留在基础的使用层面上,在遇到一些比较特殊的场景,事务可能没有生效,直接在生产上暴露了,这可能就会导致比较严重的 ...
- Spring事务失效 -方法内部调用
首先感谢网友的文章 Spring事务失效的2种情况 JDK动态代理给Spring事务埋下的坑 前提知识: 两个前提 1 注解使用 spring容器的事务管理注解 @org.springframewor ...
- 详解spring事务失效和回滚失败的场景
详解spring事务失效和回滚失败的场景 详解spring事务失效和回滚失败的场景 前言 一 .事务不生效 1.访问权限问题 2. 方法用final修饰 3.方法的内部调用 3.1 新加一个Servi ...
- springboot 调用方法事物_SpringBoot 内部方法调用,事务不起作用的原因及解决办法...
在做业务开发时,遇到了一个事务不起作用的问题.大概流程是这样的,方法内部的定时任务调用了一个带事务的方法,失败后事务没有回滚.查阅资料后,问题得到解决,记录下来分享给大家. 场景 我在这里模拟一个场景 ...
- 详细整理Spring事务失效的具体场景及解决方案
实际项目开发中,如果涉及到多张表操作时,为了保证业务数据的一致性,大家一般都会采用事务机制:好多小伙伴可能只是简单了解一下,遇到事务失效的情况,便会无从下手,溪源此篇文章给大家整理了一下常见Sprin ...
- 面试官:Spring事务失效的场景有哪些?如何解决?
作者:溪~源 blog.csdn.net/xuan_lu/article/details/107797505 实际项目开发中,如果涉及到多张表操作时,为了保证业务数据的一致性,大家一般都会采用事务机 ...
- 内部方法调用,事务不起作用的原因及解决办法
在做业务开发时,遇到了一个事务不起作用的问题.事情是这样的,方法内部的定时任务调用了一个带事务的方法,失败后事务没有回滚.查阅资料后,问题得到解决,记录下来分享给大家. 场景 我在这里模拟一个场景,大 ...
- spring同一个类中,一个方法调用另外一个注解(@Transactional)方法时,注解失效
title: "spring同一个类中,一个方法调用另外一个注解(@Transactional)方法时,注解失效" url: "https://wsk1103.githu ...
- Redis事务失效的三种场景
文章目录 Redis 事务失效的三种场景 命令入队报错 命令执行报错 乐观锁导致失效 Redis 事务失效的三种场景 Redis事务失败,有三种类型的失败场景: 命令入队报错 在事务提交之前,客户端执 ...
最新文章
- 89. a^b【快速幂模板】
- 阿里云马劲:保证云产品持续拥有稳定性的实践和思考\n
- 最短路径问题----Dijkstra算法的解释
- OpenGL之macOS上的环境搭建
- RabbitMQ 普通集群配置_04
- jrebel 远程部署 配置记录
- 也谈莫言荣获诺贝尔文学奖后我的“低调”
- ECMAScript面向对象(一)
- IntelliJ IDEA、Kotlin、PyCharm 背后公司 JetBrains 遭美国调查!
- CodeChef June Challenge 2017
- 《Android进阶指北》— Android 书籍
- 【Oracle】Oracle通过表名查询触发器
- 二建 机电工程常用材料及工程设备
- for i in range()使用方法
- 如何共享计算机网络,电脑怎么共享网络给手机上网
- 宝塔绑定域名访问不了_千字长文教你使用 宝塔面板 快速搭建网站
- 什么是pptp,什么是vps?两者有何区别?
- jQuery事件 笔记
- 第三章 part2 单调性与极值
- 梦饮酒者,旦而哭泣;梦哭泣者,旦而田猎。方其梦也,不知其梦也。 ------庄子.齐物论-节选
热门文章
- 神经结构化学习 4 图像分类的对抗性学习Adversarial learning for image classification
- 容器技术Docker K8s 44 Serverless Kubernetes(ASK)详解-ASK弹性伸缩管理
- 算法:Number of Islands(岛屿的个数)
- must be str,not int
- Ubuntu 16.04安装Docker
- module 'bit' not found:No LuaRocks module found for bit
- 1*1的卷积核与Inception
- 【生信进阶练习1000days】day9-BSgenome和AnnotationHub
- Neural Style Transfer
- Ten graph questions of about 2000 difficulty of Codeforces Round 2