当前位置: 首页 > java >正文

Spring声明式事务源码全链路剖析与设计模式深度解读


Spring声明式事务源码全链路剖析与设计模式深度解读

作者:AI
日期:2025-05-22


一、前言

Spring事务是企业级开发的基石,但“为什么有时事务失效?”、“不同传播行为背后发生了什么?”、“Spring事务源码到底如何实现?”这些问题困扰着无数开发者。本文将从源码行级剖析事务传播机制全链路跟踪设计模式变体实现三个层面,彻底解构Spring声明式事务体系。


二、Spring声明式事务核心源码全链路

2.1 事务AOP代理的生成(代理模式)

Spring通过AOP机制实现声明式事务,核心逻辑在于Bean初始化时判断是否需要代理,并生成代理对象。

源码片段:AbstractAutoProxyCreator#wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// ...是否需要事务增强判断...Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));return proxy;
}

解读:

  • 满足条件即生成JDK/CGLIB代理,后续所有对该Bean的调用都会被代理拦截。
  • 这就是经典的代理模式应用。

2.2 进入AOP拦截链(责任链模式)

代理对象的方法调用被拦截后,会进入AOP拦截器链,事务拦截器只是其中之一。

源码片段:CglibAopProxy.DynamicAdvisedInterceptor#intercept

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);if (chain.isEmpty()) {return methodProxy.invoke(target, args);} else {return new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}
}

解读:

  • 多个拦截器顺序执行,责任链模式的典范。
  • TransactionInterceptor在链中负责事务处理。

2.3 事务拦截器主流程(模板方法+责任链)

源码片段:TransactionInterceptor#invoke

public Object invoke(final MethodInvocation invocation) throws Throwable {TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);PlatformTransactionManager tm = determineTransactionManager(txAttr);String joinpointIdentification = methodIdentification(method, targetClass, txAttr);TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);Object retVal;try {retVal = invocation.proceedWithInvocation();} catch (Throwable ex) {completeTransactionAfterThrowing(txInfo, ex);throw ex;} finally {cleanupTransactionInfo(txInfo);}commitTransactionAfterReturning(txInfo);return retVal;
}

解读:

  • 事务的开启、提交、回滚、清理均在此流程完成,标准的模板方法模式
  • 业务代码通过proceedWithInvocation()继续责任链。

2.4 事务管理器与策略模式

源码片段:TransactionAspectSupport#createTransactionIfNecessary

protected TransactionInfo createTransactionIfNecessary(PlatformTransactionManager tm, TransactionAttribute txAttr, String joinpointIdentification) {if (txAttr != null && tm != null) {TransactionStatus status = tm.getTransaction(txAttr);return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);}// ...
}

解读:

  • PlatformTransactionManager是策略接口,支持多种实现(JDBC、JPA、JTA等)。
  • 运行时根据配置选择合适的策略。

2.5 事务传播机制源码全链路

传播行为决策入口

源码片段:AbstractPlatformTransactionManager#getTransaction

public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {Object transaction = doGetTransaction(); // 线程级事务资源if (isExistingTransaction(transaction)) {return handleExistingTransaction(definition, transaction, debugEnabled);}// ...无事务的处理...
}
核心传播分支源码

源码片段:handleExistingTransaction(部分)

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {Object suspendedResources = suspend(transaction);try {return startTransaction(definition, transaction, debugEnabled, suspendedResources);} catch (RuntimeException | Error beginEx) {resumeAfterBeginException(transaction, suspendedResources, beginEx);throw beginEx;}
}
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {DefaultTransactionStatus status = prepareTransactionStatus(...);status.createAndHoldSavepoint();return status;
}
// ...其它分支...

解读:

  • REQUIRES_NEW:挂起原事务、新建事务。
  • NESTED:创建JDBC保存点,支持嵌套回滚。
  • 其它传播行为:详见下表。

2.6 各传播行为源码链路与执行表

传播类型现有事务行为源码分支位置
REQUIRED加入现有事务handleExistingTransaction 默认分支
创建新事务getTransaction, startTransaction
REQUIRES_NEW挂起原事务,创建新事务handleExistingTransaction, suspend
创建新事务getTransaction, startTransaction
SUPPORTS加入现有事务handleExistingTransaction 默认分支
非事务性执行getTransaction, prepareTransactionStatus
NOT_SUPPORTED挂起原事务,非事务性执行handleExistingTransaction, suspend
非事务性执行getTransaction, prepareTransactionStatus
NEVER抛异常handleExistingTransaction, throw
非事务性执行getTransaction, prepareTransactionStatus
MANDATORY加入现有事务handleExistingTransaction 默认分支
抛异常getTransaction, throw
NESTED创建保存点,嵌套事务handleExistingTransaction, createAndHoldSavepoint
创建新事务getTransaction, startTransaction

2.7 事务挂起、恢复与保存点(进阶细节)

源码片段:挂起/恢复/保存点

protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) {if (transaction != null) {doSuspend(transaction); // 释放当前事务资源}List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();// 返回SuspendedResourcesHolder
}protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder) {if (resourcesHolder != null) {doResume(transaction, resourcesHolder.suspendedResources);}doResumeSynchronization(resourcesHolder.suspendedSynchronizations);
}DefaultTransactionStatus status = prepareTransactionStatus(...);
status.createAndHoldSavepoint(); // JDBC Savepoint

解读:

  • 挂起/恢复用于REQUIRES_NEW、NOT_SUPPORTED等。
  • NESTED通过保存点实现内层回滚而不影响外层。

2.8 事务提交/回滚与异常判定

源码片段:事务回滚判定/提交

protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {if (txInfo != null && txInfo.getTransactionStatus() != null) {if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());} else {txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());}}
}

解读:

  • 默认只对RuntimeExceptionError回滚。
  • rollbackFor/noRollbackFor优先处理。

三、所有事务传播场景全链路源码跟踪

3.1 场景举例(REQUIRES_NEW)

假设A方法有事务,B方法@Transactional(propagation = REQUIRES_NEW),A调用B:

  1. 进入B代理
  2. TransactionInterceptor#invoke
  3. createTransactionIfNecessary -> getTransaction
  4. 发现已有事务,handleExistingTransaction
  5. 判断为REQUIRES_NEW,suspend挂起A的事务
  6. startTransaction新建B的事务
  7. 执行B
  8. B事务commit/rollback
  9. resume恢复A的事务

其他传播行为可类推,详见上表。


四、设计模式在Spring事务中的变体实现

  • 代理模式:AOP代理对象生成与调用拦截
  • 策略模式PlatformTransactionManager多实现切换
  • 模板方法模式AbstractPlatformTransactionManager定义流程,子类实现细节
  • 责任链模式:AOP拦截器链,事务拦截器只是其中一环
  • 适配器模式:JDBC、JPA、JTA等适配到统一事务接口
  • 装饰器/观察者变体TransactionSynchronizationManager扩展事务回调

五、常见误区与源码分析

5.1 内部方法调用事务失效

@Service
public class A {@Transactionalpublic void methodA() { methodB(); }@Transactionalpublic void methodB() { /* ... */ }
}

分析:

  • methodB()为内部调用,未经过AOP代理,不会增强事务。

解决方案:

  • 通过外部Bean注入调用或自我注入。

六、实用速查与小结

  • 代理横切事务,策略适配场景,模板规范流程,责任链环环相扣,适配器统一接口。
  • 传播行为定范围,异常回滚看类型,自定义优先于默认。
  • 源码每一行都映射着设计思想,理解源码才能知其所以然。

七、参考资料

  • Spring事务源码官方GitHub
  • Spring官方事务文档
  • Spring源码深度解析

八、结语

Spring事务的本质,是AOP+多设计模式联合作用的工程艺术。理解每一行源码,追踪每一个传播行为的全链路,能让你真正掌控事务边界与一致性。
知其然,更知其所以然。


欢迎收藏、点赞、转发,有问题欢迎评论区一起深挖Spring源码!

http://www.xdnf.cn/news/8136.html

相关文章:

  • 【动手学深度学习】2.1. 数据操作
  • Python训练打卡Day31
  • [Harmony]实现JSON与类的双向转换
  • embedding的微调
  • MYSQL order 、group 与row_number详解
  • 3452. 好数字之和
  • 通义灵码 2.5 版深度评测:智能编程的边界在哪里?
  • 在 Spring 管理的事务环境中,获取当前事务下的 JDBC Connection对象
  • 每日算法 -【Swift 算法】Z 字形变换(Zigzag Conversion)详解与实现
  • 【机器学习基础】机器学习入门核心算法:线性回归(Linear Regression)
  • 课外知识:Python方法绑定机制与装饰器传参详解 与 实战
  • 力扣HOT100之二叉树:105. 从前序与中序遍历序列构造二叉树
  • std::initialzer_list 与花括号{}数据列表
  • 实现一个前端动态模块组件(Vite+原生JS)
  • Springboot安全策略Spring Security
  • LeetCode Hot100(滑动窗口)
  • 手机打电话时由对方DTMF响应切换多级IVR语音菜单(话术脚本与实战)
  • 【Java多线程】JUC其他常用组件
  • (视觉)分类、检测与分割在不同网络中的设计体现
  • LeetCode 滑动窗口问题 - 核心限制条件总结 (基于灵茶山艾府分类 - 详尽版)
  • Java集合再探
  • Linux LVM管理
  • 整平机:工业制造中的关键设备
  • Linux 输出输入重定向、tee命令详解
  • 高等数学-极限
  • OceanBase数据库全面指南(函数篇)函数速查表
  • 区分:union(),coalesce () 和 repartition ()
  • ProtoBuffer在Android端的编译
  • 网络编程 之网络七层模型、TCPUDP协议、JAVA IO 发展历程
  • 【2025-05-22】centos 离线安装兼容node和npm版本的pm2 和 yarn