Spring事务this自调用的理解误区?真的会让事务失效吗?

news2024/12/30 2:17:52

文章目录

      • 前言
      • this调用是什么
      • this调用事务失效案例
      • this调用事务仍然生效案例?
        • 总结
      • 如何解决this调用事务失效

前言

我们经常谈到Spring事务失效会有多种场景导致:可参考我另外一篇文章 一文清晰讲解@Transactional 注解失效场景

  • @Transactional 应用在非 public 修饰的方法上
  • @Transactional 注解属性 propagation 设置错误
  • @Transactional 注解属性 rollbackFor 设置错误
  • 同一个类中方法调用,导致@Transactional失效
  • 异常被你的 catch“吃了”导致@Transactional失效
  • 数据库引擎不支持事务
  • this自调用

这里上面谈到的this自调用真的一定会导致事务失效吗?这就是本文要探索的内容

在这里插入图片描述

this调用是什么

  • 在Java中,关键字"this"表示当前对象的引用。它可以用于引用当前对象的实例变量、调用当前对象的方法或构造函数。
class MyClass {
    public void doSomething() {
        // 执行一些操作
    }

    public void doSomethingElse() {
        this.doSomething(); // 使用"this"调用当前对象的方法
    }
}

this调用事务失效案例

@Service
public class UserService {

    @Autowired
    private MyUserMapper myUserMapper;
    
   
    public void test() {
        User user = new User();
        user.setUsername("setUsername");
        user.setPassword("setPassword");
        myUserMapper.add(user);
        this.test2();
    }
    
    @Transactional(rollbackFor = Throwable.class)
    public void test2() {
        User user = new User();
        user.setUsername("setUsername22");
        user.setPassword("setPassword22");
        myUserMapper.add(user);
        int i=1/0;
        user.setUsername("我是修改的数据哦");
        myUserMapper.update(user);    
    }
}

这种情况就是经典的this自调用导致test2方法的事务失效了!

在Spring框架中,"this"调用通常用于在同一个类的不同方法之间进行方法调用。当一个方法在同一个类中调用另一个方法时,如果使用"this"关键字进行调用,那么该调用将不会经过代理对象,而是直接在当前对象上执行方法。

Spring框架的事务管理是基于代理模式实现的。当一个类被声明为一个事务性Bean时,Spring会使用代理对象来管理该Bean的事务。代理对象会拦截方法调用,并在方法执行前后进行事务管理操作。

然而,当一个方法在同一个类的其他方法中通过"this"关键字进行调用时,调用并不会经过代理对象。这意味着事务管理的切面将无法拦截"this"调用,从而导致事务失效。

this调用事务仍然生效案例?

这里说的仍然生效其实是另外一种理解误区,其实本质来说this自调用始终是会导致事务失效的

还是上面的例子改造一下:主要观察test和test2方法上面的注解,这次我们在test方法加上了 @Transactional(rollbackFor = Throwable.class)开启了事务,然后test2方法有几种情况:

  1. public void test2()
  2. private void test2()
  3. 加上注解
 @Transactional(rollbackFor = Throwable.class,propagation = Propagation.NOT_SUPPORTED)
 public void test2()
@Service
public class UserService {

    @Autowired
    private MyUserMapper myUserMapper;
    
    @Transactional(rollbackFor = Throwable.class)
    public void test() {
        User user = new User();
        user.setUsername("setUsername");
        user.setPassword("setPassword");
        myUserMapper.add(user);
        this.test2();
    }
    
    //第2种
    //private void test2(){...}
    
    //第3种
    //@Transactional(rollbackFor = Throwable.class,propagation = Propagation.NOT_SUPPORTED)
 	//public void test2(){...}
 	
    public void test2() {
        User user = new User();
        user.setUsername("setUsername22");
        user.setPassword("setPassword22");
        myUserMapper.add(user);
        int i=1/0;
        user.setUsername("我是修改的数据哦");
        myUserMapper.update(user);    
    }
}

实际运行会发现,上面test2的第3种情况,里面的事务都会进行回滚!!!难道是搞错了? Spring的this自调用不会导致事务失效?

之前我就是一直这样陷入了误区,以为是这样的,其实真实的原因很简单:

test() 方法使用了 @Transactional(rollbackFor = Throwable.class) 注解,表明该方法应该在一个事务中执行。当通过 this.test2() 调用 test2() 方法时,它将在当前事务的上下文中被调用!!!

在 Spring 中,默认情况下,@Transactional 注解被设置为 Propagation.REQUIRED,这意味着如果当前已经存在一个事务,那么方法将在该事务中执行;如果没有事务,将创建一个新的事务。因此,在 test() 方法中调用 this.test()test() 方法将在同一个事务中执行。

总结
  • 所以并不是Spring自调用不会导致事务失效,而是理解问题!
  • test2前两种情况是方法上面根本就没有@Transactional注解,本身就没有事务这一说法,也就不存在所谓的失效、生效了!
  • 而第3种情况加上@Transactional(rollbackFor = Throwable.class,propagation = Propagation.NOT_SUPPORTED)想要方法不支持事务,但是发现它还是有事务??所以确实是它注解上的事务失效了(它本质是为了不要事务,但是现在有事务了,所以是失效了)!!然后因为事务传播特性导致它加入了test方法的事务,看起来是事务生效了(反着来,这里好好品味一下

如何解决this调用事务失效

  • 采用AopContext.currentProxy().方法B名()来进行调用—注意需要在启动类上加一个注解@EnableAspectJAutoProxy(exposeProxy = true)
  • ApplicationContext.getBean()
  • 在当前类中注入自己
  • 使用手动事务

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1044087.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法训练营第四十九天 | 动态规划 part 10 | 买卖股票的最佳时机i、ii

目录 121. 买卖股票的最佳时机思路代码 122.买卖股票的最佳时机II思路代码 121. 买卖股票的最佳时机 Leetcode 思路 贪心:记录最低值,并且遍历股票逐个寻找股票卖出最大值 动态规划: dp[i][0] 表示第i天持有股票所得最多现金 dp[i][1] 表示…

uniapp - 微信小程序实现腾讯地图位置标点展示,将指定地点进行标记选点并以一个图片图标展示出来(详细示例源码,一键复制开箱即用)

效果图 在uniapp微信小程序平台端开发,简单快速的实现在地图上进行位置标点功能,使用腾讯地图并进行标点创建和设置(可以自定义标记点的图片)。 你只需要复制代码,改个标记图标和位置即可。

工地临时用电之智慧用电:全方位保障用电安全

随着科技进步和智能化的发展,工地用电管理也迎来了智慧化的革新。智慧用电,作为智慧工地的重要组成部分,通过集中式管理和创新的技术手段,为工地提供了全方位的用电安全保障。 针对工地临时用 的现状及系统结构,力安科…

ElementUI之动态树+数据表格+分页->动态树,动态表格

动态树动态表格 1.动态树 //src/components/LeftNav.vue <template><el-menu router :default-active"$route.path" default-active"2" class"el-menu-vertical-demo" background-color"#334157" text-color"#fff&quo…

OWASP Top 10漏洞解析(1)- A1:Broken Access Control 访问控制失效

作者&#xff1a; gentle_zhou 原文链接&#xff1a;OWASP Top 10漏洞解析&#xff08;1&#xff09;- A1:Broken Access Control 访问控制失效-云社区-华为云 Web应用程序安全一直是一个重要的话题&#xff0c;它不但关系到网络用户的隐私&#xff0c;财产&#xff0c;而且关…

Logic Pro X10.7.9(mac乐曲制作软件)

Logic Pro X是由苹果公司开发的一款专业音频制作软件&#xff0c;主要用于音乐制作、录音、混音和母带处理等方面。以下是Logic Pro X的特点&#xff1a; 强大的音频编辑功能&#xff1a;Logic Pro X提供了丰富的音频编辑工具&#xff0c;包括波形编辑器、音频自动化、时间拉伸…

【Linux】——基操指令(一)

个人主页 代码仓库 C语言专栏 初阶数据结构专栏 Linux专栏 LeetCode刷题 算法专栏 目录 前言 基操前的碎碎念 计算机的层状结构 基础指令 查看登录用户指令 查看用户指令 查看当前所处工作目录 清屏指令 基操指令 ls命令 cd命令 makdir指令 rmdir指令 &…

UE学习记录06----根据Actor大小自适应相机位置

背景&#xff1a; staticMesh 会根据业务需要随时变化&#xff0c;然后通过staticMesh的大小自适应相机位置&#xff0c;捕捉画面用来预览该模型&#xff0c;使模型在画布中不会太大导致显示不全&#xff0c;也不会太小 参考&#xff1a; UE实现相机聚焦物体功能_右弦GISer的…

TensorFlow入门(二、基本步骤)

深度学习是机器学习领域中的一个研究方向,它被引入机器学习使其更接近于最初的目标——人工智能。 深度学习的本质其实就是一个拟合函数&#xff0c;通过不断的“喂入”数据&#xff08;比如图片或者视频&#xff09;来调节神经网络的参数&#xff0c;从而找到输入数据的特征范…

嵌入式Linux应用开发-Framebuffer 应用编程

嵌入式Linux应用开发-Framebuffer 应用编程 第五章 Framebuffer 应用编程5.1 LCD 操作原理5.2 涉及的 API 函数5.2.1 open 函数5.2.2 ioctl 函数5.2.3 mmap 函数 5.3 Framebuffer 程序分析5.3.1 打开设备5.3.2 获取 LCD 参数5.3.3 映射 Framebuffer5.3.4 描点函数5.3.5 随便画几…

主机安装elasticsearch后无法登陆

问题描述 2023年7月31日11点02分&#xff0c;主机安装elasticsearch后无法登陆&#xff0c;通过后台查看主机宕机状态&#xff0c;CPU达到100%&#xff0c;按业务侧要求执行重启操作后发现主机黑屏无法正常进入系统&#xff0c;系统卡死。 2&#xff0e;原因分析 2.1通过故障…

自定义注解实现Redis分布式锁、手动控制事务和根据异常名字或内容限流的三合一的功能

自定义注解实现Redis分布式锁、手动控制事务和根据异常名字或内容限流的三合一的功能 文章目录 [toc] 1.依赖2.Redisson配置2.1单机模式配置2.2主从模式2.3集群模式2.4哨兵模式 3.实现3.1 RedisConfig3.2 自定义注解IdempotentManualCtrlTransLimiterAnno3.3自定义切面Idempote…

「Go框架」gin框架是如何处理panic的?

本文我们介绍下recover在gin框架中的应用。 首先&#xff0c;在golang中&#xff0c;如果在子协程中遇到了panic&#xff0c;那么主协程也会被终止。如下&#xff1a; package mainimport ("github.com/gin-gonic/gin" )func main() {r : gin.Default()// 在子协程中…

Apache DolphinScheduler 在奇富科技的首个调度异地部署实践

奇富科技&#xff08;原360数科&#xff09;是人工智能驱动的信贷科技服务平台&#xff0c;致力于凭借智能服务、AI研究及应用、安全科技&#xff0c;赋能金融机构提质增效&#xff0c;助推普惠金融高质量发展&#xff0c;让更多人享受到安全便捷的金融科技服务。作为国内领先的…

【RocketMQ】sendDefaultImpl call timeout 问题及其解决办法

问题描述&#xff1a; org.apache.rocketmq.remoting.exception.RemotingTooMuchRequestException: sendDefaultImpl call timeout解决&#xff1a; 需要开放10911、10909这两个端口 需修改broker.conf&#xff0c;设置公网IP 启动broker时&#xff0c;需用-c conf/broker.…

通俗易懂-OpenCV角点检测算法(Harris、Shi-Tomas算法实现)

目录 1 图像的特征 2&#xff0c;Harris角点检测 2.1 代码实现 2.2结果展示 3&#xff0c;Shi-Tomasi角点检测算法 3.1 &#xff0c; 代码实现 3.2结果展示 1 图像的特征 2&#xff0c;Harris角点检测 、 2.1 代码实现 import cv2 as cv import matplotlib.pyplot as …

RocketMQ —消费者负载均衡

消费者从 Apache RocketMQ 获取消息消费时&#xff0c;通过消费者负载均衡策略&#xff0c;可将主题内的消息分配给指定消费者分组中的多个消费者共同分担&#xff0c;提高消费并发能力和消费者的水平扩展能力。本文介绍 Apache RocketMQ 消费者的负载均衡策略。 背景信息​ …

Magic Battery for Mac:让你的设备电量管理变得轻松简单

Mac电脑用户们&#xff0c;你们是否曾经为了给设备充电而感到烦恼&#xff1f;是否希望能够方便地查看连接设备的电量情况&#xff1f;现在&#xff0c;有了Magic Battery for macOS&#xff0c;这些问题都将成为过去&#xff01; Magic Battery是一个实用的应用程序&#xff…

Spring Boot事件机制浅析

1、概述 在设计模式中&#xff0c;观察者模式是一个比较常用的设计模式。维基百科解释如下&#xff1a; 观察者模式是软件设计模式的一种。在此种模式中&#xff0c;一个目标对象管理所有相依于它的观察者对象&#xff0c;并且在它本身的状态改变时主动发出通知。这通常透过呼…

曲线救国-通过Magisk安装burp证书到系统根目录

0x01前言 需要对某APP做渗透测试&#xff0c;但该APP做了限制&#xff1a;不信任用户证书。因此需要将burp证书导入到存放系统证书目录下。虽然手机装了Magic&#xff0c;但似乎root有点问题。其挂载有问题&#xff0c;导致无法将 最初尝试&#xff1a;mount -o rw,remount -t…