死磕Spring之AOP篇 - Spring 事务详解 (7)

通过 Pointcut 事务切点筛选出来的 Bean,会创建一个代理对象,Bean 内部肯定定义了 @Transactional 注解,如果是类上定义的 @Transactional 注解,每个方法都需要进行事务处理。代理对象的事务拦截处理在 TransactionInterceptor 拦截器中,实现了 MethodInterceptor 方法拦截器,也就是实现了 Object invoke(MethodInvocation invocation) 这个方法,一起来看看 TransactionInterceptor 这个类

结构类图:

死磕Spring之AOP篇 - Spring 事务详解

// TransactionInterceptor.java @Override @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { // 目标类 Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // 在事务中执行方法调用器 return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); }

调用 invokeWithinTransaction(..) 方法,在事务中执行方法调用器,如下:

// TransactionAspectSupport.java protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable { // If the transaction attribute is null, the method is non-transactional. TransactionAttributeSource tas = getTransactionAttributeSource(); // <1> 获取 `@Transactional` 注解对应的 TransactionAttribute 对象(如果在 AnnotationTransactionAttributeSource 解析过则取缓存) final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); // <2> 获取 PlatformTransactionManager 事务管理器(可以指定,没有指定则获取默认的) final PlatformTransactionManager tm = determineTransactionManager(txAttr); // <3> 获取方法的唯一标识,默认都是 `类名.方法名` final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); // <4> 如果已有 `@Transactional` 注解对应的 TransactionAttribute 对象,或者是一个非回调偏向的事务管理器(默认不是) if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. // <4.1> 创建 TransactionInfo 事务信息对象,绑定在 ThreadLocal 中 // 包含一个 DefaultTransactionStatus 事务状态对象 TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal; try { // <4.2> 继续执行方法调用器 retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { // <4.3> 如果捕获到异常,则在这里完成事务,进行回滚或者提交 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { // <4.4> `finally` 语句块,释放 ThreadLocal 中的 TransactionInfo 对象,设置为上一个事务信息对象(没有的话为空) cleanupTransactionInfo(txInfo); } // <4.5> 正常情况,到这里完成事务 commitTransactionAfterReturning(txInfo); // <4.6> 返回执行结果 return retVal; } // <5> 否则,就是支持回调的事务管理器,编程式事务(回调偏向),暂时忽略 else { // ..... } }

整个过程有点复杂,我们一步一步来看

获取 @Transactional 注解对应的 TransactionAttribute 对象(如果在 AnnotationTransactionAttributeSource 解析过则取缓存),在 Pointcut 事务切点中已经分析过

获取 PlatformTransactionManager 事务管理器,需要指定,在 Spring Boot 中默认为 DataSourceTransactionManager

获取方法的唯一标识,默认都是 类名.方法名

如果已有 @Transactional 注解对应的 TransactionAttribute 对象,或者不是一个回调偏向的事务管理器(默认不是)

调用 createTransactionIfNecessary(..) 方法,创建 TransactionInfo 事务信息对象(包含一个 DefaultTransactionStatus 事务状态对象),绑定在 ThreadLocal 中

继续执行方法调用器(执行方法)

如果捕获到异常,则在这里完成事务,进行回滚或者提交,调用 completeTransactionAfterThrowing(..) 方法

finally 语句块,释放 ThreadLocal 中的 TransactionInfo 对象,设置为上一个事务信息对象(没有的话为空)

正常情况,到这里完成事务,调用 commitTransactionAfterReturning(..) 方法

返回执行结果

否则,就是支持回调的事务管理器,编程式事务(回调偏向),暂时忽略

整个过程的主流程不复杂,我们可以看到上面的第 4 步,可以把这一步分为四个步骤:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygsff.html