这是一个非常常见的关于 Spring 事务传播机制 的问题,核心问题是:

在同一个类中,方法 A 调用方法 B,而方法 B 上有 @Transactional 注解。当调用方法 A 时,如果发生异常,方法 B 的事务会生效吗?


简短回答:

不会生效!

在 Spring 中,默认使用的是基于 代理(Proxy) 的事务管理机制,只有外部调用带有 @Transactional 注解的方法时才会开启事务。

如果是同一个类中的方法直接调用(即内部调用),Spring 的事务注解将失效


示例代码说明

@Service
public class MyService { public void methodA() {
// 做一些操作
methodB(); // 内部调用methodB
} @Transactional
public void methodB() {
// 数据库操作
}
}

️问题:

  • 你调用 methodA(),它内部调用了 methodB()
  • 即使 methodB() 上有 @Transactional 注解,事务也不会生效

为什么事务不生效?

因为 Spring 的事务是通过 动态代理(JDK Proxy 或 CGLIB) 实现的:

  • 当你从外部调用 methodB(),Spring 会拦截这个调用,并在调用前后开启/提交事务。
  • 但当你在类内部调用 methodB(),这是普通的 Java 方法调用,绕过了代理对象,Spring 无法进行事务控制。

如何解决这个问题?

方案一:将方法拆分到不同的类中

methodB() 放到另一个 Service 类中:

@Service
public class MyService { @Autowired
private AnotherService anotherService; public void methodA() {
// 做一些操作
anotherService.methodB(); // 外部调用
}
} @Service
public class AnotherService { @Transactional
public void methodB() {
// 数据库操作
}
}

这样事务就会生效了。


方案二:通过 AopContext.currentProxy() 获取代理对象(慎用)

你可以通过以下方式获取当前类的代理对象来调用 methodB()

@Service
public class MyService implements ApplicationContextAware { private static ApplicationContext applicationContext; @Transactional
public void methodB() {
// 数据库操作
} public void methodA() {
// 获取当前类的代理对象
MyService proxy = (MyService) AopContext.currentProxy();
proxy.methodB(); // 使用代理调用
} @Override
public void setApplicationContext(ApplicationContext ctx) {
applicationContext = ctx;
}
}

️ 注意事项:

  • 需要在配置文件中启用暴露代理:<aop:aspectj-autoproxy expose-proxy="true"/>
  • 或者使用注解方式:@EnableAspectJAutoProxy(exposeProxy = true)
  • 此方式可实现功能,但会让代码耦合 Spring 框架,一般推荐优先使用方案一。

补充:事务传播行为(Propagation Behavior)

如果你希望方法B的行为能被方法A控制,可以指定事务传播行为,例如:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
// 总是开启一个新事务
}

但这仍然需要保证 methodB() 是通过代理调用的才行。


总结

场景 事务是否生效 说明
同一类内调用带 @Transactional 的方法 不生效 Spring 无法拦截内部方法调用
不同类之间调用带 @Transactional 的方法 生效 通过代理对象调用,事务生效
使用 AopContext.currentProxy() 调用 可以生效 需要设置 expose-proxy=true

有关Spring事务的传播机制的更多相关文章

  1. 数据库的特性与隔离级别和spring事务的传播机制和隔离级别

    首先数据库的特性就是 ACID: Atomicity 原子性:所有事务是一个整体,要么全部成功,要么失败 Consistency 一致性:在事务开始和结束前,要保持一致性状态 Isolation 隔离 ...

  2. Spring事务之传播机制

    Spring事务传播机制:Spring在TransactionDefinition接口中规定了种类型的事务传播行为,它们规定了事务方法和事务方法发生嵌套时事务如何进行传播.即协调已经有事务标识的方法之 ...

  3. spring事务的传播机制新解

    以下是事物的传播机制: @Transactional(propagation=Propagation.REQUIRED)如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)@Transacti ...

  4. 通俗易懂的spring事务的传播机制讲解!

    spring事务理解 前提两个都是事务的方法,并且两个方法会进行调用,调用方统一使用required 举例有两个方法: required 如果当前上下文存在事务,被调用方则加入该调用方的事务,没有的话 ...

  5. Spring事务的传播行为 @Transactional(转)

    Spring事务的传播行为 在service类前加上@Transactional,声明这个service所有方法需要事务管理.每一个业务方法开始时都会打开一个事务. Spring默认情况下会对运行期例 ...

  6. Spring事务的传播行为 @Transactional

    Spring事务的传播行为http://blog.csdn.net/cuker919/article/details/5957209 在service类前加上@Transactional,声明这个se ...

  7. 关于事务,事务的特性,spring事务的传播特性

    1.什么是事务: 事务是程序中一系列严密的操作,所有操作执行必须成功完成,否则在每个操作所做的更改将会被撤销,这也是事务的原子性(要么成功,要么失败). 2.事务特性: 事务特性分为四个:原子性(At ...

  8. Spring事务的传播特性和隔离级别

    事务的几种传播特性1. PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务.如果没有事务则开启2. PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务 ...

  9. Spring事务的传播行为

      本文主要介绍下Spring事务中的传播行为. 事务传播行为介绍 Spring中的7个事务传播行为: |事务行为|说明 | |:--|:--| |PROPAGATION_REQUIRED | 支持当 ...

  10. Spring事务的传播:PROPAGATION_REQUIRED

    PROPAGATION_REQUIRED-- 支持当前事务,如果当前没有事务,就新建一个事务.这是最常见的选择. ServiceA { void methodA() { ServiceB.method ...

随机推荐

  1. mac、windows 配置python国内镜像源

    前言 我们在使用python pip安装第三方库时,经常会发生超时报错,这是可以指定临近的镜像源快速更新. mac中 在用户目录下建立一个".pip"目录,到目录里新建一个文件&q ...

  2. HoloLens2 开发推荐配置

    博客地址:https://www.cnblogs.com/zylyehuo/ 1.win11 pro+vs2019+unity2018+MRTK2.6.1 2.win10 pro+vs2019+uni ...

  3. Docker镜像介绍

    一.Docker镜像介绍 镜像是Docker的三大核心概念之一. Docker运行容器前需要本地存在对应的镜像,如果镜像不存在本地,Docker会尝试先从默认的镜像仓库下载(默认使用Docker Hu ...

  4. ORB算法介绍 Introduction to ORB (Oriented FAST and Rotated BRIEF)

    Introduction to ORB (Oriented FAST and Rotated BRIEF) 1. Introduction ORB(Oriented FAST and Rotated ...

  5. HTML5 给网站添加图标

    1.首先将图标上传到对应的目录下 2.在网页的index.html,添加已下代码到<head>标签里 <link rel="icon" href="i_ ...

  6. 【安卓】使用Handler出现的警告

    使用Handler出现的警告 零.原由 安卓中使用Hander时出现了如下警告: This Handler class should be static or leaks might occur (a ...

  7. Ubuntu14.04系统设置菜单选项缺失

    最近折腾Ubuntu14.04,突然有一天发现系统设置里少了好多菜单选项,莫名的zuo ji,解决办法如下,留爪. 问题图示 解决办法 #首先打开终端输入,终端快捷键[Ctrl + Alt + T] ...

  8. 头晕的android SDK Manager and 找不到真机

    这张图很完美!可是出问题就头晕了. 问题场景:执行Andriod.bat出现下面界面后,然后跳出Andriod SDK的界面: android SDK Manager的界面就孤零零的几条记录挂在那里. ...

  9. zk基础—3.集群与核心参数

    大纲 1.zk单机模式是如何启动的 2.zk集群是如何部署和启动的 3.zk集群部署要用什么样配置的机器 4.如何合理设置zk的JVM参数以及内存大小 5.zk配置的核心参数之tickTime.dat ...

  10. Kylin-Server-V10-SP3物理机安装简要过程

    1.下载镜像 链接: https://eco.kylinos.cn/partners/mirror.html?class_id=1&query_key=V10 选择: 银河麒麟高级服务器操作系 ...