有关Spring事务的传播机制
这是一个非常常见的关于 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事务的传播机制的更多相关文章
- 数据库的特性与隔离级别和spring事务的传播机制和隔离级别
首先数据库的特性就是 ACID: Atomicity 原子性:所有事务是一个整体,要么全部成功,要么失败 Consistency 一致性:在事务开始和结束前,要保持一致性状态 Isolation 隔离 ...
- Spring事务之传播机制
Spring事务传播机制:Spring在TransactionDefinition接口中规定了种类型的事务传播行为,它们规定了事务方法和事务方法发生嵌套时事务如何进行传播.即协调已经有事务标识的方法之 ...
- spring事务的传播机制新解
以下是事物的传播机制: @Transactional(propagation=Propagation.REQUIRED)如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)@Transacti ...
- 通俗易懂的spring事务的传播机制讲解!
spring事务理解 前提两个都是事务的方法,并且两个方法会进行调用,调用方统一使用required 举例有两个方法: required 如果当前上下文存在事务,被调用方则加入该调用方的事务,没有的话 ...
- Spring事务的传播行为 @Transactional(转)
Spring事务的传播行为 在service类前加上@Transactional,声明这个service所有方法需要事务管理.每一个业务方法开始时都会打开一个事务. Spring默认情况下会对运行期例 ...
- Spring事务的传播行为 @Transactional
Spring事务的传播行为http://blog.csdn.net/cuker919/article/details/5957209 在service类前加上@Transactional,声明这个se ...
- 关于事务,事务的特性,spring事务的传播特性
1.什么是事务: 事务是程序中一系列严密的操作,所有操作执行必须成功完成,否则在每个操作所做的更改将会被撤销,这也是事务的原子性(要么成功,要么失败). 2.事务特性: 事务特性分为四个:原子性(At ...
- Spring事务的传播特性和隔离级别
事务的几种传播特性1. PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务.如果没有事务则开启2. PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务 ...
- Spring事务的传播行为
本文主要介绍下Spring事务中的传播行为. 事务传播行为介绍 Spring中的7个事务传播行为: |事务行为|说明 | |:--|:--| |PROPAGATION_REQUIRED | 支持当 ...
- Spring事务的传播:PROPAGATION_REQUIRED
PROPAGATION_REQUIRED-- 支持当前事务,如果当前没有事务,就新建一个事务.这是最常见的选择. ServiceA { void methodA() { ServiceB.method ...
随机推荐
- mac、windows 配置python国内镜像源
前言 我们在使用python pip安装第三方库时,经常会发生超时报错,这是可以指定临近的镜像源快速更新. mac中 在用户目录下建立一个".pip"目录,到目录里新建一个文件&q ...
- HoloLens2 开发推荐配置
博客地址:https://www.cnblogs.com/zylyehuo/ 1.win11 pro+vs2019+unity2018+MRTK2.6.1 2.win10 pro+vs2019+uni ...
- Docker镜像介绍
一.Docker镜像介绍 镜像是Docker的三大核心概念之一. Docker运行容器前需要本地存在对应的镜像,如果镜像不存在本地,Docker会尝试先从默认的镜像仓库下载(默认使用Docker Hu ...
- ORB算法介绍 Introduction to ORB (Oriented FAST and Rotated BRIEF)
Introduction to ORB (Oriented FAST and Rotated BRIEF) 1. Introduction ORB(Oriented FAST and Rotated ...
- HTML5 给网站添加图标
1.首先将图标上传到对应的目录下 2.在网页的index.html,添加已下代码到<head>标签里 <link rel="icon" href="i_ ...
- 【安卓】使用Handler出现的警告
使用Handler出现的警告 零.原由 安卓中使用Hander时出现了如下警告: This Handler class should be static or leaks might occur (a ...
- Ubuntu14.04系统设置菜单选项缺失
最近折腾Ubuntu14.04,突然有一天发现系统设置里少了好多菜单选项,莫名的zuo ji,解决办法如下,留爪. 问题图示 解决办法 #首先打开终端输入,终端快捷键[Ctrl + Alt + T] ...
- 头晕的android SDK Manager and 找不到真机
这张图很完美!可是出问题就头晕了. 问题场景:执行Andriod.bat出现下面界面后,然后跳出Andriod SDK的界面: android SDK Manager的界面就孤零零的几条记录挂在那里. ...
- zk基础—3.集群与核心参数
大纲 1.zk单机模式是如何启动的 2.zk集群是如何部署和启动的 3.zk集群部署要用什么样配置的机器 4.如何合理设置zk的JVM参数以及内存大小 5.zk配置的核心参数之tickTime.dat ...
- Kylin-Server-V10-SP3物理机安装简要过程
1.下载镜像 链接: https://eco.kylinos.cn/partners/mirror.html?class_id=1&query_key=V10 选择: 银河麒麟高级服务器操作系 ...