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());}}
}
解读:
- 默认只对
RuntimeException
和Error
回滚。 rollbackFor
/noRollbackFor
优先处理。
三、所有事务传播场景全链路源码跟踪
3.1 场景举例(REQUIRES_NEW)
假设A方法有事务,B方法@Transactional(propagation = REQUIRES_NEW)
,A调用B:
- 进入B代理
TransactionInterceptor#invoke
createTransactionIfNecessary
->getTransaction
- 发现已有事务,
handleExistingTransaction
- 判断为REQUIRES_NEW,
suspend
挂起A的事务 startTransaction
新建B的事务- 执行B
- B事务
commit
/rollback
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源码!