Spring事务this自调用的理解误区?真的会让事务失效吗? 您所在的位置:网站首页 spring中如何使用事务 Spring事务this自调用的理解误区?真的会让事务失效吗?

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

2024-02-19 05:30| 来源: 网络整理| 查看: 265

文章目录 前言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方法有几种情况:

public void test2()private void test2()加上注解 @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()在当前类中注入自己使用手动事务


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有