最近了解到,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 {

// AOP的PointcutAdvisor
// PointcutAdvisor = PointCut + Advice
@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;
}

// PointCut
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
// Accept protected @Transactional methods on CGLIB proxies, as of 6.0.
return new AnnotationTransactionAttributeSource(false);
}

// Advice
@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负责将PointCutAdvice注入到AOP中,没有什么复杂的逻辑

下面介绍一下TransactionAttributeSourceTransactionInterceptor

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);
}

// 解析方法上的Transactional注解
@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 {
//执行目标方法crud
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// crud执行异常回滚事务
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
//提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}

其中调用了PlatformTransactionManager去执行物理事务,是负责执行增强任务的Advice

PlatformTransactionManager

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中事务的传播模式有以下几种:

事务分为逻辑事务和物理事务:

  • 逻辑事务是指代码中事务的操作,即表面的业务逻辑
  • 物理事务是数据库层面的操作,即从获取数据库连接到数据库执行事务完毕整个过程

事务失效的几种场景

这个部分是根据网上的博客总结出来的😎

  1. 方法为private:事务代理类要求被代理方法必须是public的,否则不进行代理
    • 从 Spring 6.0 开始,protected方法可以被 CGLIB 代理
  2. 方法用final修饰:Spring事务底层是基于AOP的,被final修饰的方法无法被代理类重写
  3. 方法内部调用:同理,代理类根据@Transactional代理方法,方法内部调用会绕过代理
  4. 多线程调用、异常捕获不对(默认捕获RunningTimeError)、未被Spring管理等等

参考: