SpringDataSourceAndTransaction-源码-01

总结摘要
Spring 数据源与事务源码介绍01

前言

事务的实现原理是 Spring AOP。

用户启用注解驱动的事务功能后,Spring beanFactory 将注册1个事务相关的 AOP。

用户在 bean 的类定义或方法定义中声明事务注解@Transactional,beanFactory 创建该 bean 时,将解析事务注解中的属性作为事务属性。

用户调用方法时,首先进入事务 AOP 中,即方法中的业务逻辑被事务包裹。

AOP

事务的实现原理是 Spring AOP。

简介

org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration自动配置类中注册了BeanFactoryTransactionAttributeSourceAdvisorTransactionInterceptorTransactionAttributeSource,共同构建了切面。

类定义

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

事务流程概述

简单执行流程概述

  1. 外部调用 @Transactional注解修饰的方法。
  2. org.springframework.transaction.interceptor.TransactionInterceptor#invoke 事务拦截器拦截方法。
  3. org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction 事务处理的主要逻辑。
  4. 事务前置处理
    1. 获取数据库连接
    2. 创建事务
    3. 事务同步
  5. invocation.proceedWithInvocation() 执行业务逻辑
  6. 事务后置处理
    1. 提交或者回退事务
    2. 释放数据库连接
    3. 事务同步

创建事务与提交或回退事务

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