前言
事务的实现原理是 Spring AOP。
用户启用注解驱动的事务功能后,Spring beanFactory 将注册1个事务相关的 AOP。
用户在 bean 的类定义或方法定义中声明事务注解@Transactional,beanFactory 创建该 bean 时,将解析事务注解中的属性作为事务属性。
用户调用方法时,首先进入事务 AOP 中,即方法中的业务逻辑被事务包裹。
AOP
事务的实现原理是 Spring AOP。
简介
org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration自动配置类中注册了BeanFactoryTransactionAttributeSourceAdvisor、TransactionInterceptor和TransactionAttributeSource,共同构建了切面。
类定义
1
2
3
4
5
6
7
8
9
| // org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor
public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {}
// org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {}
// org.springframework.transaction.interceptor.TransactionInterceptor
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
}
|
切面逻辑
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
| abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
// 配置 class 级别的过滤条件
protected TransactionAttributeSourcePointcut() {
setClassFilter(new TransactionAttributeSourceClassFilter());
}
// 方法级别的过滤条件。
@Override
public boolean matches(Method method, Class<?> targetClass) {
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
// 类级别的过滤条件。
// 调用`org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#isCandidateClass`方法。
// 底层使用`SpringTransactionAnnotationParser`判断类(或方法)是否配置事务属性。
private class TransactionAttributeSourceClassFilter implements ClassFilter {
@Override
public boolean matches(Class<?> clazz) {
if (TransactionalProxy.class.isAssignableFrom(clazz) ||
TransactionManager.class.isAssignableFrom(clazz) ||
PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.isCandidateClass(clazz));
}
}
}
|
拦截器逻辑
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
28
| public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
@Override
@Nullable
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
@Override
public Object getTarget() {
return invocation.getThis();
}
@Override
public Object[] getArguments() {
return invocation.getArguments();
}
});
}
}
|
事务流程概述
简单执行流程概述
- 外部调用
@Transactional注解修饰的方法。 - org.springframework.transaction.interceptor.TransactionInterceptor#invoke 事务拦截器拦截方法。
- org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction 事务处理的主要逻辑。
- 事务前置处理
- 获取数据库连接
- 创建事务
- 事务同步
- 等
- invocation.proceedWithInvocation() 执行业务逻辑
- 事务后置处理
- 提交或者回退事务
- 释放数据库连接
- 事务同步
- 等
创建事务与提交或回退事务
1
2
3
4
5
6
7
8
9
| TransactionAttribute txAttr; // 获取事务属性。
PlatformTransactionManager txManager; // 获取事务管理器,依赖 txAttr。
TransactionStatus status = txManager.getTransaction(txAttr); // 开启事务,得到事务状态。依赖 txManager 和 txAttr。事务状态 status 可能被封装到 TransactionInfo 中。
//执行业务逻辑
txManager.commit(status)/txManager.rollback(status); // 提交或回退事务
|
数据源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| DataSourceTransactionObject txObject = new DataSourceTransactionObject();
Connection newCon = obtainDataSource().getConnection();
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
// 标识连接资源跟事务同步
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
// 标识激活事务
txObject.getConnectionHolder().setTransactionActive(true);
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
// 真正激活事务
TransactionSynchronizationManager.setActualTransactionActive(true);
// 初始化同步行为
TransactionSynchronizationManager.initSynchronization();
|
补充知识
类实现
1
2
3
4
5
6
7
| DataSourceTransactionManager.DataSourceTransactionObject -> JdbcTransactionObjectSupport -> SavepointManager,SmartTransactionObject
ConnectionHolder -> ResourceHolderSupport -> ResourceHolder
AbstractPlatformTransactionManager#transactionSynchronization = SYNCHRONIZATION_ALWAYS; // 始终激活事务同步,即使是空事务。
TransactionSynchronizationManager#actualTransactionActive // 标识当前是否有一个实际的事务处于活动状态,即示当前线程是否与一个实际的事务相关联。
|
事务流程详情
源码摘录
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
| // 仅保留 @Transactional 方法实际使用逻辑,省略其它逻辑。
// org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// 获取事务属性源`TransactionAttributeSource`,直接从缓存获取。
TransactionAttributeSource tas = getTransactionAttributeSource();
// 获取事务属性`TransactionAttribute`,从缓存中获取。
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 探测事务管理器`TransactionManager`。
// Spring 中不同的方法支持不同的事务管理器,通过注解中属性`Transactional#transactionManager`配置。
final TransactionManager tm = determineTransactionManager(txAttr);
// 转型为`PlatformTransactionManager`。
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
// 构建方法标识符字符串。默认为类名称与方法名称拼接,不包含方法参数。
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// 创建事务如果有必要的话。
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
// 执行业务逻辑。
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
// 如果抛出异常,则进行异常处理。如果事务属性配置该异常处理逻辑为回滚,则回滚事务,否则继续尝试提交事务。
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 始终执行清理逻辑,作为 finally 逻辑。主要工作是清除线程中的事务信息,设置为 null 或前一个事务信息(嵌套事务场景)。栈结构。
cleanupTransactionInfo(txInfo);
}
// 如果未抛出异常,则提交事务。
commitTransactionAfterReturning(txInfo);
return retVal;
}
|
流程
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
42
43
44
45
46
47
| // 入口方法
// org.springframework.transaction.interceptor.TransactionInterceptor#invoke
// org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction
--> 获取事务属性源`TransactionAttributeSource`,直接从缓存获取。`getTransactionAttributeSource();`。
--> 获取事务属性`TransactionAttribute`。
--|> org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute
--|> 此处可以直接从缓存获取。
--|> 在 beanFactory 的每个 bean 创建时,事务相关的 AOP 会缓存相关信息。
--> 探测事务管理器`TransactionManager`。
--> 如果入参中的事务属性`txAttr`为空,或 beanFactory 为空,则返回缓存`TransactionAspectSupport#transactionManager`中的`TransactionManager`。
--|> 默认`txAttr`必定不为空,跳过。
--> 优先根据注解`@Transactional`中配置的属性`transactionManager`(事务管理器 bean 名称)查找。如果找到,则缓存并返回。
--|> 可知,Spring 中不同的方法支持不同的事务管理器。
--|> 缓存到属性`TransactionAspectSupport#transactionManagerCache`中。
--> 其次,如果配置了属性`TransactionAspectSupport#transactionManagerBeanName`,则根据该 bean 查找。如果找到,则缓存并返回。
--> 否则,如果缓存`TransactionAspectSupport#transactionManager`不为空,则返回。
--> 否则,如果缓存`TransactionAspectSupport#transactionManagerCache`中存在默认值,则返回。
--> 否则,根据 bean 类型在 beanFactory 中查询`TransactionManager`实现类,并以默认值缓存到`TransactionAspectSupport#transactionManagerCache`。
--|> 默认第一次查询时会以该方式查找。
--> Spring reactive 相关的逻辑,略。
--> 将上一步骤获取的`TransactionManager`转型为`PlatformTransactionManager`。
--|> `asPlatformTransactionManager(tm)`
--> 简单的类型强转。
--> 如果 tm 不存在,则抛出异常。
--> 构建方法标识符字符串。`methodIdentification(method, targetClass, txAttr);`
--> 默认为类名称与方法名称拼接,不包含方法参数。
--> 如果事务属性为空,或事务管理器非`CallbackPreferringPlatformTransactionManager`。
--|> 满足条件,执行下文逻辑。当前事务属性不为空,使用`JdbcTransactionManager`。
--> 创建事务如果有必要的话。
--|> org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary
--|> 待补充
--> 执行业务逻辑。`retVal = invocation.proceedWithInvocation();`。略。
--> 如果抛出异常,则进行异常处理。如果事务属性配置该异常处理逻辑为回滚,则回滚事务,否则继续尝试提交事务。
--|> org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing
--> 如果事务属性配置该异常处理逻辑为回滚,则回滚事务。
--|> org.springframework.transaction.support.AbstractPlatformTransactionManager#rollback
--> org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback
--> 否则继续尝试提交事务。
--|> org.springframework.transaction.support.AbstractPlatformTransactionManager#commit
--> 始终执行清理逻辑,作为 finally 逻辑。主要工作是清除线程中的事务信息,设置为 null 或前一个事务信息(嵌套事务场景)。栈结构。
--|> org.springframework.transaction.interceptor.TransactionAspectSupport#cleanupTransactionInfo
--> org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo#restoreThreadLocalStatus
--> 如果未抛出异常,则提交事务。
--|> org.springframework.transaction.interceptor.TransactionAspectSupport#commitTransactionAfterReturning
--> txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());提交事务。
--> org.springframework.transaction.support.AbstractPlatformTransactionManager#commit
--> 否则,CallbackPreferringPlatformTransactionManager 相关逻辑。略。
|
构建
AOP 通用流程
1
2
3
4
5
6
7
| // InfrastructureAdvisorAutoProxyCreator/AspectJAwareAdvisorAutoProxyCreator/AnnotationAwareAspectJAutoProxyCreator
// 三者均为`AbstractAdvisorAutoProxyCreator`的实现类。
--> org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
--> ...
--> org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean)
--> org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut#matches
--|> 判断
|
事务 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
42
43
| // org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute
@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
// First, see if we have a cached value.
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// Value will either be canonical value indicating there is no transaction attribute,
// or an actual transaction attribute.
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
}
else {
// We need to work it out.
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
if (txAttr instanceof DefaultTransactionAttribute) {
DefaultTransactionAttribute dta = (DefaultTransactionAttribute) txAttr;
dta.setDescriptor(methodIdentification);
dta.resolveAttributeStrings(this.embeddedValueResolver);
}
if (logger.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
|
流程
1
2
3
4
5
6
7
8
9
10
11
12
| // org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut#matches
--> 探测方法及类上声明的事务属性`TransactionAttribute`。
--|> org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute
--> 首先使用缓存,key 包含类与方法签名信息。
--> 如果缓存不存在,则构建缓存。
--> 探测方法及类上声明的事务属性
--|> org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#computeTransactionAttribute
--> 忽略 non-public 的方法。
--> 首先查询方法级别的事务属性。
--> 其次查询类级别的事务属性。
--> 其它判断,略。
--> 缓存事务属性。默认是`DefaultTransactionAttribute`类。
|
END