news 2026/2/2 1:56:49

spring 事务是如何实现的?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
spring 事务是如何实现的?

Spring 的事务实现本质上是基于 AOP(面向切面编程) + 动态代理,在不修改原有业务代码的情况下,把事务的开始、提交、回滚、异常处理这些横切关注点“织入”到目标方法中。

下面从最核心的几个层面逐步拆解(以声明式事务@Transactional为例,这是 95%+ 项目实际使用的模式):

1. 整体架构分层(最重要的一张思维导图)

Spring 事务抽象层(PlatformTransactionManager) ↑ 具体实现(DataSourceTransactionManager / JpaTransactionManager / JtaTransactionManager 等) ↑ TransactionSynchronizationManager(线程本地资源管理器) ↑ AOP 切面(TransactionInterceptor + 各种 Advice) ↑ 动态代理(JDK Proxy / CGLIB) ↑ 你的业务 Bean(@Service 中的 @Transactional 方法)

2. 核心实现步骤(运行时发生了什么)

阶段发生了什么关键类 / 组件
容器启动解析@EnableTransactionManagement<tx:annotation-driven/>TransactionManagementConfigurer / AnnotationDrivenBeanDefinitionParser
注册BeanFactoryTransactionAttributeSourceAdvisor(事务切面 Advisor)
Bean 创建对于有@Transactional的类/方法,Spring 创建代理对象ProxyFactory / CglibAopProxy / JdkDynamicAopProxy
外部调用方法时调用的是代理对象的方法(不是原始对象)
代理拦截TransactionInterceptor(核心 Advice)被执行TransactionInterceptor.invoke()
读取@Transactional的属性(propagation、isolation、timeout、rollbackFor 等)TransactionAttributeSource
事务开始调用PlatformTransactionManager.getTransaction(definition)→ 创建 / 加入 / 挂起事务
把 Connection / TransactionStatus 绑定到 ThreadLocalTransactionSynchronizationManager.bindResource()
目标方法执行真正执行你的业务代码(原始对象的方法)
正常结束提交:commit()TransactionManager.commit(status)
异常抛出判断是否需要回滚(默认 RuntimeException & Error 回滚,可自定义 rollbackFor)rollbackOn() 判断
回滚:rollback()TransactionManager.rollback(status)
清理解绑 ThreadLocal 资源,恢复挂起的旧事务(如果有嵌套)cleanupTransaction()

3. 传播行为(Propagation)是怎么实现的?(最常考点)

传播级别代码中是否有事务外面有事务吗?实际效果底层实现方式简述
REQUIRED新开事务getTransaction() 创建新事务
REQUIRED加入已有事务复用已有 TransactionStatus
REQUIRES_NEW总是新建独立事务(外面事务被挂起)suspend() → create new → resume()
NESTED使用 savepoint(嵌套子事务)createSavepoint() / rollbackToSavepoint()
SUPPORTS跟随外面事务,没有就不用事务只读模式或无事务
MANDATORY抛异常(必须在事务中调用)检查当前是否有事务,没有就 IllegalState
NEVER抛异常(禁止在事务中调用)同上
NOT_SUPPORTED挂起外面事务,以非事务方式执行suspend() → 执行 → resume()

注意:NESTED 是唯一基于 savepoint 的传播行为,其他的都是基于 Connection 的 commit/rollback。

4. 为什么自调用(this.method())事务会失效?

因为代理只对外部调用有效

@ServicepublicclassUserService{@Transactionalpublicvoidouter(){// 这里有事务inner();// ← this.inner() 直接调用原始对象的方法 → 绕过代理 → 无事务}@Transactionalpublicvoidinner(){// 期望有事务,但实际没有(自调用场景)}}

解决办法(任选其一):

  • @Transactional的类注入自己(不推荐,循环依赖)
  • AopContext.currentProxy()(需开启 exposeProxy=true)
  • 把 inner 抽到另一个@Service类里(最推荐)
  • 用编程式事务TransactionTemplate

5. 线程安全 & 资源绑定核心 —— TransactionSynchronizationManager

这是一个ThreadLocal大管家,里面存了:

  • 当前线程的 Connection / Session / TransactionStatus
  • 资源是否只读
  • 事务同步器列表(可以注册回调:beforeCommit、afterCommit、afterCompletion 等)

几乎所有事务相关的操作最终都会走到这里取/放资源。

总结一句话

Spring 事务的实现可以浓缩为:

“用动态代理(AOP)拦截方法 → 根据 @Transactional 属性通过 PlatformTransactionManager 在 ThreadLocal 中绑定/管理数据库连接和事务状态 → 在方法正常结束或异常时统一 commit/rollback”

最核心的两句话:

  • 没有 AOP 动态代理 → 就没有声明式事务
  • 没有 PlatformTransactionManager → 就没有真正的事务控制(Spring 只做协调)

如果你想更深入看某一块(比如 savepoint 实现细节、DataSourceTransactionManager 源码、Reactive 事务区别、多数据源切换等),可以告诉我,我可以继续拆更细。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/29 19:27:28

【Django毕设源码分享】基于Django的游戏辅助和内容更新系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/1/30 13:50:42

NetDXF:.NET平台下的DXF文件处理技术解决方案

NetDXF&#xff1a;.NET平台下的DXF文件处理技术解决方案 【免费下载链接】netDxf .net dxf Reader-Writer 项目地址: https://gitcode.com/gh_mirrors/ne/netDxf 在工程设计与CAD开发领域&#xff0c;DXF文件作为数据交换的核心载体&#xff0c;其处理效率直接影响项目…

作者头像 李华
网站建设 2026/1/30 3:59:56

为什么使用postman发送请求时不会有跨域问题?

使用 Postman 发送 HTTP 请求时几乎永远不会遇到跨域&#xff08;CORS&#xff09;问题&#xff0c;而浏览器里同样的请求却经常报 No Access-Control-Allow-Origin header is present on the requested resource. 或类似错误。 根本原因就一句话&#xff1a; CORS&#xff0…

作者头像 李华
网站建设 2026/1/30 6:24:41

YOLOE-v8l-seg模型实测,检测精度提升的秘密揭晓

YOLOE-v8l-seg模型实测&#xff0c;检测精度提升的秘密揭晓 你是否遇到过这样的困境&#xff1a;训练好的YOLOv8模型在COCO上表现优异&#xff0c;一换到真实产线场景——比如工厂零件识别、医疗器械分类、小众品牌商品检测——准确率就断崖式下跌&#xff1f;不是漏检就是误判…

作者头像 李华
网站建设 2026/1/30 15:30:05

加载示例音频快速测试,Emotion2Vec+ Large系统自检方法

加载示例音频快速测试&#xff0c;Emotion2Vec Large系统自检方法 1. 为什么需要一次快速自检&#xff1f; 你刚启动 Emotion2Vec Large 语音情感识别系统&#xff0c;浏览器打开 http://localhost:7860&#xff0c;界面加载完成——但此时你真正知道它是否“活”着吗&#x…

作者头像 李华