最近了解到,Spring中的事务是由AOP实现的(当然这里说的是声明式事务),至于里面具体的逻辑是怎么样的,今天花了一天的时间看代码,总算弄是明白了大概流程😎,至于里面很多技术细节还没去深挖,先这样吧╮(╯_╰)╭
Spring 事务相关的API
先看看概念:
事务操作相关的API
@Transactional
- Spring事务注解
@EnableTranSactionManagement
- Spring事务模块驱动
事务抽象相关的API
PlatformTransactionManager
- Spring平台事务管理器,负责执行事务的关键类
TransactionStatus
- Spring事务状态
TransactionDefinition
- Spring事务定义
ProxyTransactionManagementConfiguration
- Spring事务代理配置类
AOP相关的API
BeanFactoryTransactionAttrubuteSourceAdvisor
- Spring事务PointcutAdvisor实现
TransactionInterceptor
- 事务执行切面,负责事务执行的核心类
TransactionAttributeSource
- Spring事务属性源
TransactionAnnotationParser
- 解析器,负责扫描并解析所有的带有@Transactional的方法或类,并将数据封装为TransactionAttributeSource
TransactionSynchronizationAdapter
- 事务同步器,感知事务是成功还是失败,在事务提交前后通知,这个在做一些需要监听事务状态的业务需求估计会比较有用吧🤨
实现原理
ProxyTransactionManagementConfiguration
是通过@EnableTranSactionManagement
注入的核心配置类,内部实际注册了三个Bean,这三个Bean其实是AOP的三部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| @Configuration(proxyBeanMethods = false) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) @ImportRuntimeHints(TransactionRuntimeHints.class) public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor( TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(transactionAttributeSource); advisor.setAdvice(transactionInterceptor); if (this.enableTx != null) { advisor.setOrder(this.enableTx.<Integer>getNumber("order")); } return advisor; }
@Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() { return new AnnotationTransactionAttributeSource(false); }
@Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) { TransactionInterceptor interceptor = new TransactionInterceptor(); interceptor.setTransactionAttributeSource(transactionAttributeSource); if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; } }
|
其中BeanFactoryTransactionAttributeSourceAdvisor
负责将PointCut
和Advice
注入到AOP中,没有什么复杂的逻辑
下面介绍一下TransactionAttributeSource
和TransactionInterceptor
TransactionAttributeSource
上面注入了一个AnnotationTransactionAttributeSource
,我们来看看这个Bean做了什么
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) { this.publicMethodsOnly = publicMethodsOnly; if (jta12Present || ejb3Present) { this.annotationParsers = new LinkedHashSet<>(4); this.annotationParsers.add(new SpringTransactionAnnotationParser()); if (jta12Present) { this.annotationParsers.add(new JtaTransactionAnnotationParser()); } if (ejb3Present) { this.annotationParsers.add(new Ejb3TransactionAnnotationParser()); } } else { this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser()); } }
@Override @Nullable protected TransactionAttribute findTransactionAttribute(Method method) { return determineTransactionAttribute(method); }
@Nullable protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) { for (TransactionAnnotationParser parser : this.annotationParsers) { TransactionAttribute attr = parser.parseTransactionAnnotation(element); if (attr != null) { return attr; } } return null; }
|
所以这个类的作用大概就是解析所有方法上的Transactional注解然后封装为TransactionAttributeSource
,最后担任PointCut
角色
TransactionInterceptor
执行事务的核心方法,这个方法很长很复杂没有耐心看了🥲,看了网上的博客大概是这么说的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable {
TransactionAttributeSource tas = getTransactionAttributeSource(); final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); final PlatformTransactionManager tm = determineTransactionManager(txAttr); final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; try { retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo); } commitTransactionAfterReturning(txInfo); return retVal; }
|
其中调用了PlatformTransactionManager
去执行物理事务,是负责执行增强任务的Advice
PlatformTransactionManager是Spring对于事务模型的抽象,它代表事务的整体执行过程。
1 2 3 4 5 6 7 8
| public interface PlatformTransactionManager { TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException; void commit(TransactionStatus var1) throws TransactionException; void rollback(TransactionStatus var1) throws TransactionException; }
|
其他的一些知识点
Spring中事务的传播行为
Spring中事务的传播模式有以下几种:

事务分为逻辑事务和物理事务:
- 逻辑事务是指代码中事务的操作,即表面的业务逻辑
- 物理事务是数据库层面的操作,即从获取数据库连接到数据库执行事务完毕整个过程
事务失效的几种场景
这个部分是根据网上的博客总结出来的😎
- 方法为
private
:事务代理类要求被代理方法必须是public
的,否则不进行代理
- 从 Spring 6.0 开始,
protected
方法可以被 CGLIB 代理
- 方法用
final
修饰:Spring事务底层是基于AOP的,被final修饰的方法无法被代理类重写
- 方法内部调用:同理,代理类根据
@Transactional
代理方法,方法内部调用会绕过代理
- 多线程调用、异常捕获不对(默认捕获
RunningTimeError
)、未被Spring管理等等
参考: