Spring 源码阅读 74:BeanFactoryTransactionAttributeSourceAdvisor 分析

简介: 【1月更文挑战第9天】本文通过对 BeanFactoryTransactionAttributeSourceAdvisor 类的分析,了解了 Spring 是如何通过 AOP 来完成事务的管理的,本文的内容需要你对 Spring 的 AOP 的实现原理有一定的了解。


基于 Spring Framework v5.2.6.RELEASE

概述

Spring 的事务管理基于 AOP 特性,因此,事务管理的增强逻辑需要一个 Advisor 来提供,这便是 BeanFactoryTransactionAttributeSourceAdvisor,本文我们来分析它的原理。

类关系

它是 PointcutAdvisor 的实现类,我们开发时配置的切面通过 Spring 解析后得到的也是一个 PointcutAdvisor,因此,它们的原理应该是相似的。所以,本文会通过以下几个方面来进行分析:

  1. Spring 创建它的具体过程
  2. 如何匹配被增强的类型
  3. 如何匹配被增强的方法
  4. 通过增强逻辑实现事务管理的具体原理

创建

它是在 Spring 解析配置的时候被创建的,以下是 ProxyTransactionManagementConfiguration 中创建 BeanFactoryTransactionAttributeSourceAdvisor 的方法。

// org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor@Bean(name=TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
publicBeanFactoryTransactionAttributeSourceAdvisortransactionAdvisor(
TransactionAttributeSourcetransactionAttributeSource, TransactionInterceptortransactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisoradvisor=newBeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
advisor.setAdvice(transactionInterceptor);
if (this.enableTx!=null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
   }
returnadvisor;
}

方法中,通过无参构造方法创建了 BeanFactoryTransactionAttributeSourceAdvisor 对象,并初始化了一些属性。它并没有显式地声明构造方法,因此我们分别来看几个属性的设置。

transactionAttributeSource 属性

transactionAttributeSource 属性的值,来自方法参数,需要 Spring 来注入,这个值的来源是同一个配置类中的另外一个方法。

// org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration#transactionAttributeSource@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
publicTransactionAttributeSourcetransactionAttributeSource() {
returnnewAnnotationTransactionAttributeSource();
}

其中,AnnotationTransactionAttributeSource 的构造方法如下。

publicAnnotationTransactionAttributeSource() {
this(true);
}

再进入另外一个构造方法。

publicAnnotationTransactionAttributeSource(booleanpublicMethodsOnly) {
this.publicMethodsOnly=publicMethodsOnly;
if (jta12Present||ejb3Present) {
this.annotationParsers=newLinkedHashSet<>(4);
this.annotationParsers.add(newSpringTransactionAnnotationParser());
if (jta12Present) {
this.annotationParsers.add(newJtaTransactionAnnotationParser());
      }
if (ejb3Present) {
this.annotationParsers.add(newEjb3TransactionAnnotationParser());
      }
   }
else {
this.annotationParsers=Collections.singleton(newSpringTransactionAnnotationParser());
   }
}

AnnotationTransactionAttributeSource 的构造方法中,主要初始化了两个属性。

  • publicMethodsOnly 的值,从上一段代码的方法调用this(true)传入,它的值是true
  • annotationParsers 是一个列表,根据当前类加载器能够加载到的类型,添加不同的事物注解解析器,限于本文讨论的范围,我们只考虑 SpringTransactionAnnotationParser。

advice 属性

advice 属性的值,同样来自方法参数,它包含的是 Advisor 的增强逻辑,这里注入的值是 TransactionInterceptor 类型,来源也是用一配置类中的另一个方法。

// org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration#transactionInterceptor@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
publicTransactionInterceptortransactionInterceptor(TransactionAttributeSourcetransactionAttributeSource) {
TransactionInterceptorinterceptor=newTransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager!=null) {
interceptor.setTransactionManager(this.txManager);
   }
returninterceptor;
}

它的构造方法也不包含任何逻辑,并且,注入了上一部分介绍了 transactionAttributeSource。除此之外,如果成员变量txManager不为空,则赋值给他的 transactionManager 属性。

transactionManager 是事务管理器,可以在当前配置类的父类中,找到它的来源。

TransactionManager

以下就是初始化成员变量txManager的方法。

@Autowired(required=false)
voidsetConfigurers(Collection<TransactionManagementConfigurer>configurers) {
if (CollectionUtils.isEmpty(configurers)) {
return;
   }
if (configurers.size() >1) {
thrownewIllegalStateException("Only one TransactionManagementConfigurer may exist");
   }
TransactionManagementConfigurerconfigurer=configurers.iterator().next();
this.txManager=configurer.annotationDrivenTransactionManager();
}

方法添加了 @Autowired 注解,参数是 TransactionManagementConfigurer 类型的集合,Spring 会找到容器中所有的该类型的 Bean,组成一个集合,作为参数执行这个方法的逻辑。

当方法传入的集合中有且只有一个元素的时候,它的annotationDrivenTransactionManager会被执行,并将的到的结果赋值给txManager

以下是 TransactionManagementConfigurer 接口的定义。

publicinterfaceTransactionManagementConfigurer {
TransactionManagerannotationDrivenTransactionManager();
}

里面只有一个方法,返回 TransactionManager 类型的结果,一个配置类可以通过实现 TransactionManagementConfigurer 接口来自定义 TransactionManager 的创建逻辑。

pointcut 属性

除了配置方法中设置的值以外,BeanFactoryTransactionAttributeSourceAdvisor 还有一个定义了初始值的属性pointcut,它表示切入点,负责匹配目标类和目标方法。

// org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor#pointcutprivatefinalTransactionAttributeSourcePointcutpointcut=newTransactionAttributeSourcePointcut() {
@Override@NullableprotectedTransactionAttributeSourcegetTransactionAttributeSource() {
returntransactionAttributeSource;
   }
};

pointcut属性的类型是 TransactionAttributeSourcePointcut,并在初始化时实现了getTransactionAttributeSource方法。

进入 TransactionAttributeSourcePointcut 的构造方法。

// org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut#TransactionAttributeSourcePointcutprotectedTransactionAttributeSourcePointcut() {
setClassFilter(newTransactionAttributeSourceClassFilter());
}

构造方法中调用了setClassFilter方法给classFilter成员变量赋值,值是一个通过构造方法创建的 TransactionAttributeSourceClassFilter 类型的实例。

TransactionAttributeSourceClassFilter 是 TransactionAttributeSourcePointcut 的内部类,以下是它的源码。

privateclassTransactionAttributeSourceClassFilterimplementsClassFilter {
@Overridepublicbooleanmatches(Class<?>clazz) {
if (TransactionalProxy.class.isAssignableFrom(clazz) ||PlatformTransactionManager.class.isAssignableFrom(clazz) ||PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
returnfalse;
      }
TransactionAttributeSourcetas=getTransactionAttributeSource();
return (tas==null||tas.isCandidateClass(clazz));
   }
}

我们都知道,在 Advisor 中,pointcut的主要作用是匹配目标类型和方法,以上的 ClassFilter 给 TransactionAttributeSourcePointcut 提供了一个类型匹配的具体逻辑。

在通过 Pointcut 进行目标类型和方法的匹配时,会先从 Pointcut 中获取一个 ClassFilter 或 MethodMatcher,然后通过它们的matches方法来判断。

TransactionAttributeSourcePointcut 中,获取 ClassFilter 和 MethodMatcher 的方法定义在其父类 StaticMethodMatcherPointcut 中。

@OverridepublicClassFiltergetClassFilter() {
returnthis.classFilter;
}
@OverridepublicfinalMethodMatchergetMethodMatcher() {
returnthis;
}

其中,ClassFilter 就是在构造方法中初始化的 TransactionAttributeSourceClassFilter,而 MethodMatcher 就是其自身。

下面分别来看一下,它是如何做目标类和方法的匹配的。

目标类型匹配

目标类型的匹配逻辑在 TransactionAttributeSourceClassFilter 类的matches方法中。

// org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut.TransactionAttributeSourceClassFilter#matches@Overridepublicbooleanmatches(Class<?>clazz) {
if (TransactionalProxy.class.isAssignableFrom(clazz) ||PlatformTransactionManager.class.isAssignableFrom(clazz) ||PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
returnfalse;
   }
TransactionAttributeSourcetas=getTransactionAttributeSource();
return (tas==null||tas.isCandidateClass(clazz));
}

首先,确保目标类型不是 TransactionalProxy、PlatformTransactionManager 或者 PersistenceExceptionTranslator,然后,通过getTransactionAttributeSource方法,获取到transactionAttributeSource属性,通过他的isCandidateClass方法来判断。

// org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#isCandidateClass@OverridepublicbooleanisCandidateClass(Class<?>targetClass) {
for (TransactionAnnotationParserparser : this.annotationParsers) {
if (parser.isCandidateClass(targetClass)) {
returntrue;
      }
   }
returnfalse;
}

isCandidateClass方法的逻辑,就是遍历annotationParsers集合中的每一个 TransactionAnnotationParser 元素,执行过它们的isCandidateClass方法,进行判断。

根据之前的分析,我们这里只考虑集合中包含 SpringTransactionAnnotationParser 的情况,以下是它的isCandidateClass方法。

// org.springframework.transaction.annotation.SpringTransactionAnnotationParser#isCandidateClass@OverridepublicbooleanisCandidateClass(Class<?>targetClass) {
returnAnnotationUtils.isCandidateClass(targetClass, Transactional.class);
}

再进入 AnnotationUtils 的isCandidateClass方法。

// org.springframework.core.annotation.AnnotationUtils#isCandidateClass(java.lang.Class<?>, java.lang.Class<? extends java.lang.annotation.Annotation>)publicstaticbooleanisCandidateClass(Class<?>clazz, Class<?extendsAnnotation>annotationType) {
returnisCandidateClass(clazz, annotationType.getName());
}
// org.springframework.core.annotation.AnnotationUtils#isCandidateClass(java.lang.Class<?>, java.lang.String)publicstaticbooleanisCandidateClass(Class<?>clazz, StringannotationName) {
if (annotationName.startsWith("java.")) {
returntrue;
   }
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
returnfalse;
   }
returntrue;
}

如果类的名称是java.开头的,则返回true。然后,再 AnnotationsScanner 的hasPlainJavaAnnotationsOnly方法判断,除了此方法返回true的类型,其余情况都返回true

// org.springframework.core.annotation.AnnotationsScanner#hasPlainJavaAnnotationsOnly(java.lang.Class<?>)staticbooleanhasPlainJavaAnnotationsOnly(Class<?>type) {
return (type.getName().startsWith("java.") ||type==Ordered.class);
}

名称以java.开头的情况前面已经判断过了,因此这里就是判断类型是否是 Ordered 类型。

总结下来,匹配类的逻辑就是,确保类不是 TransactionalProxy、PlatformTransactionManager、PersistenceExceptionTranslator、Ordered 这几种类型之一。

目标方法匹配

方法的匹配逻辑在 TransactionAttributeSourcePointcut 的matches方法中。

@Overridepublicbooleanmatches(Methodmethod, Class<?>targetClass) {
TransactionAttributeSourcetas=getTransactionAttributeSource();
return (tas==null||tas.getTransactionAttribute(method, targetClass) !=null);
}

匹配的逻辑依然是通过成员变量transactionAttributeSourcegetTransactionAttribute方法,从方法获取事务相关的注解配置属性信息,如果获取到的结果不为空,则符合匹配条件。

AnnotationTransactionAttributeSource 中的getTransactionAttribute方法,继承自父类 AbstractFallbackTransactionAttributeSource。

// org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute@Override@NullablepublicTransactionAttributegetTransactionAttribute(Methodmethod, @NullableClass<?>targetClass) {
if (method.getDeclaringClass() ==Object.class) {
returnnull;
   }
// First, see if we have a cached value.ObjectcacheKey=getCacheKey(method, targetClass);
TransactionAttributecached=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) {
returnnull;
      }
else {
returncached;
      }
   }
else {
// We need to work it out.TransactionAttributetxAttr=computeTransactionAttribute(method, targetClass);
// Put it in the cache.if (txAttr==null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
      }
else {
StringmethodIdentification=ClassUtils.getQualifiedMethodName(method, targetClass);
if (txAttrinstanceofDefaultTransactionAttribute) {
            ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
         }
if (logger.isTraceEnabled()) {
logger.trace("Adding transactional method '"+methodIdentification+"' with attribute: "+txAttr);
         }
this.attributeCache.put(cacheKey, txAttr);
      }
returntxAttr;
   }
}

首先判断方法不是在 Object 类中声明的,然后,从缓存中读取数据,如果缓存中没有数据,则执行获取注解配置信息的逻辑。因此,这个方法中重点要分析的逻辑是最外层的else语句块中的逻辑。

方法最终返回的txAttr是通过computeTransactionAttribute方法得到的,无论获取到的txAttr是否为空,都会将其添加到缓存集合attributeCache中,并最终作为结果返回。

computeTransactionAttribute的源码如下。

// org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#computeTransactionAttribute@NullableprotectedTransactionAttributecomputeTransactionAttribute(Methodmethod, @NullableClass<?>targetClass) {
// Don't allow no-public methods as required.if (allowPublicMethodsOnly() &&!Modifier.isPublic(method.getModifiers())) {
returnnull;
   }
// The method may be on an interface, but we need attributes from the target class.// If the target class is null, the method will be unchanged.MethodspecificMethod=AopUtils.getMostSpecificMethod(method, targetClass);
// First try is the method in the target class.TransactionAttributetxAttr=findTransactionAttribute(specificMethod);
if (txAttr!=null) {
returntxAttr;
   }
// Second try is the transaction attribute on the target class.txAttr=findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr!=null&&ClassUtils.isUserLevelMethod(method)) {
returntxAttr;
   }
if (specificMethod!=method) {
// Fallback is to look at the original method.txAttr=findTransactionAttribute(method);
if (txAttr!=null) {
returntxAttr;
      }
// Last fallback is the class of the original method.txAttr=findTransactionAttribute(method.getDeclaringClass());
if (txAttr!=null&&ClassUtils.isUserLevelMethod(method)) {
returntxAttr;
      }
   }
returnnull;
}

方法的逻辑并不复杂,大致如下:

  1. 如果事务注解只对public修饰的方法有效,但是当前的目标方法method不是public修饰的方法,直接返回空。
  2. 通过 AopUtils 的getMostSpecificMethod方法,获取目标方法method的具体实现方法,也就是说,如果当前的目标方法是一个接口中定义的方法,则根据当前目标类型获取到类型中的实现方法specificMethod
  3. 通过findTransactionAttribute方法从specificMethod获取 TransactionAttribute,如果不为空,则作为结果返回。
  4. 通过findTransactionAttribute方法从specificMethod所在的类型获取 TransactionAttribute,如果不为空,则作为结果返回。
  5. 如果methodspecificMethod不是同一个方法,则对method和它所在的类型执行3、4步的操作。
  6. 以上都得不到结果的情况下,返回空。

上面的步骤中,获取 TransactionAttribute 的findTransactionAttribute方法被多次调用,它的定义如下。

// org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.Class<?>)@Override@NullableprotectedTransactionAttributefindTransactionAttribute(Class<?>clazz) {
returndetermineTransactionAttribute(clazz);
}
// org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.reflect.Method)@Override@NullableprotectedTransactionAttributefindTransactionAttribute(Methodmethod) {
returndetermineTransactionAttribute(method);
}

其中的具体逻辑交给了determineTransactionAttribute方法。

// org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#determineTransactionAttribute@NullableprotectedTransactionAttributedetermineTransactionAttribute(AnnotatedElementelement) {
for (TransactionAnnotationParserparser : this.annotationParsers) {
TransactionAttributeattr=parser.parseTransactionAnnotation(element);
if (attr!=null) {
returnattr;
      }
   }
returnnull;
}

主要的逻辑就是遍历annotationParsers集合中的注解解析器,来解析参数中传入的 AnnotatedElement,来获取 TransactionAttribute。前面我们提到过,这里的注解解析器,我们只考虑 SpringTransactionAnnotationParser,因此,进入它的parseTransactionAnnotation方法。

// org.springframework.transaction.annotation.SpringTransactionAnnotationParser#parseTransactionAnnotation(java.lang.reflect.AnnotatedElement)@Override@NullablepublicTransactionAttributeparseTransactionAnnotation(AnnotatedElementelement) {
AnnotationAttributesattributes=AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes!=null) {
returnparseTransactionAnnotation(attributes);
   }
else {
returnnull;
   }
}

逻辑非常简单,就是获取到方法或者类上的 Transactional 注解,然后将注解的属性封装成一个 TransactionAttribute 并返回。

总结下来就是,如果目标方法或者所在的类型,标记了 Transactional 注解,那么就会被负责事务管理的拦截器匹配到,并对其进行增强。

增强逻辑

了解了目标类型和方法的匹配,最后在看具体的增强逻辑。根据 Spring AOP 的机制,执行增强逻辑时,需要从 BeanFactoryTransactionAttributeSourceAdvisor 对象中,通过getAdvice方法,获取到增强逻辑的拦截器,再执行拦截器的invoke方法。

前文中已经介绍过,BeanFactoryTransactionAttributeSourceAdvisor 的advice属性是在配置类中初始化的,它的类型是 TransactionInterceptor,它的主要继承关系如下。

可以确认,它实现了 MethodInterceptor 接口,并且它的invoke方法,就是增强逻辑所在的方法。

// org.springframework.transaction.interceptor.TransactionInterceptor#invoke@Override@NullablepublicObjectinvoke(MethodInvocationinvocation) throwsThrowable {
// 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...returninvokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}

其中的核心逻辑是调用了定义在父类 TransactionAspectSupport 中的invokeWithinTransaction方法。

先分析方法的参数。其中,methodtargetClass是目标方法和类型,相比起来,更值得注意的是第三个参数invocation,它的类型是 InvocationCallback。

// org.springframework.transaction.interceptor.TransactionAspectSupport.InvocationCallback@FunctionalInterfaceprotectedinterfaceInvocationCallback {
ObjectproceedWithInvocation() throwsThrowable;
}

InvocationCallback 是一个函数式接口,其中的proceedWithInvocation方法,返回了一个 Object 结果。在调用方法时,这里传入的值是invocation::proceed,也就是说,这里的invocation参数传入的是目标方法的调用。了解完参数后,再看方法体。

这个方法的代码超过了 100 行,我们只分析其中的核心部分,完整的方法体代码可以到 TransactionAspectSupport 类的源码中查看。

// org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction// If the transaction attribute is null, the method is non-transactional.TransactionAttributeSourcetas=getTransactionAttributeSource();
finalTransactionAttributetxAttr= (tas!=null?tas.getTransactionAttribute(method, targetClass) : null);
finalTransactionManagertm=determineTransactionManager(txAttr);
// 省略部分代码PlatformTransactionManagerptm=asPlatformTransactionManager(tm);
finalStringjoinpointIdentification=methodIdentification(method, targetClass, txAttr);
if (txAttr==null||!(ptminstanceofCallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.TransactionInfotxInfo=createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
ObjectretVal;
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 (Throwableex) {
// target invocation exceptioncompleteTransactionAfterThrowing(txInfo, ex);
throwex;
   }
finally {
cleanupTransactionInfo(txInfo);
   }
if (vavrPresent&&VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...TransactionStatusstatus=txInfo.getTransactionStatus();
if (status!=null&&txAttr!=null) {
retVal=VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
      }
   }
commitTransactionAfterReturning(txInfo);
returnretVal;
}
// 省略部分代码

方法体中的内容,可以归纳为以下几个关键步骤:

  • 通过createTransactionIfNecessary方法,得到一个 TransactionInfo 类型的txInfo对象。从方法名称和返回的结果来看,这一步应该是根据需要创建了事务,并得到事务的信息。
  • 然后,在try语句中调用目标方法,并的到执行的返回值retVal
  • 如果执行目标方法的过程中出现了异常,则执行completeTransactionAfterThrowing方法,处理异常的情况,再将异常抛出。
  • 在finally语句块中执行cleanupTransactionInfo方法,清除异常信息。
  • 如果上述过程中没有出现异常,则执行commitTransactionAfterReturning方法,提交事务。

从上述归纳中可以看出,最主要的步骤都是通过调用相应的方法来完成的,接下来,我们就逐一分析这些方法。

createTransactionIfNecessary 方法

// org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary@SuppressWarnings("serial")
protectedTransactionInfocreateTransactionIfNecessary(@NullablePlatformTransactionManagertm,
@NullableTransactionAttributetxAttr, finalStringjoinpointIdentification) {
// If no name specified, apply method identification as transaction name.if (txAttr!=null&&txAttr.getName() ==null) {
txAttr=newDelegatingTransactionAttribute(txAttr) {
@OverridepublicStringgetName() {
returnjoinpointIdentification;
         }
      };
   }
TransactionStatusstatus=null;
if (txAttr!=null) {
if (tm!=null) {
status=tm.getTransaction(txAttr);
      }
else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping transactional joinpoint ["+joinpointIdentification+"] because no transaction manager has been configured");
         }
      }
   }
returnprepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

其中,有一行关键的代码,如下:

status=tm.getTransaction(txAttr);

这里对执行tmgetTransaction方法,获取食物状态,开启事务也是在这里完成的。tm的类型是 PlatformTransactionManager,它是一个事务管理器对象。事务管理器是在 Spring 的事务管理配置类中注册到 Spring 容器的,这一部分在前文已经介绍过。

事务管理器中会通过 JDBC 的方式,获取到数据库连接对象 Connection,通过调用setAutoCommit(false)将自动提交设置为false,就开启了事务。

目标方法的执行

开启事务之后,就可以开始执行目标方法了,由于目标方法执行时抛出的异常可能会导致事务会滚,因此,目标方法的调用被放在了try语句块中,方便对抛出的一场进行处理。

completeTransactionAfterThrowing 方法

如果目标方法跑出了一场,则会交给catch语句块中的completeTransactionAfterThrowing方法来处理。

// org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowingprotectedvoidcompleteTransactionAfterThrowing(@NullableTransactionInfotxInfo, Throwableex) {
if (txInfo!=null&&txInfo.getTransactionStatus() !=null) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for ["+txInfo.getJoinpointIdentification() +"] after exception: "+ex);
      }
if (txInfo.transactionAttribute!=null&&txInfo.transactionAttribute.rollbackOn(ex)) {
try {
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
         }
catch (TransactionSystemExceptionex2) {
logger.error("Application exception overridden by rollback exception", ex);
ex2.initApplicationException(ex);
throwex2;
         }
catch (RuntimeException|Errorex2) {
logger.error("Application exception overridden by rollback exception", ex);
throwex2;
         }
      }
else {
// We don't roll back on this exception.// Will still roll back if TransactionStatus.isRollbackOnly() is true.try {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
         }
catch (TransactionSystemExceptionex2) {
logger.error("Application exception overridden by commit exception", ex);
ex2.initApplicationException(ex);
throwex2;
         }
catch (RuntimeException|Errorex2) {
logger.error("Application exception overridden by commit exception", ex);
throwex2;
         }
      }
   }
}

这个方法的源码虽然不少,但是逻辑其实非常简单。首先,会判断当前抛出的异常是不是属于 Transaction 注解中rollbackFor属性配置的异常的范畴,如果是,则说明当前抛出的异常,是需要回滚的异常,此时,就会调用事务管理器的rollback方法进行回滚,否则,通过commit方法进行提交,不过这里的提交并不是直接提交事务,而是在提交前会判断事务信息,只在符合提交条件的情况下进行提交。

cleanupTransactionInfo 方法

在目标方法执行的finally语句块中会cleanupTransactionInfo方法,从方法名称可以看出它的作用是清理事务信息。

// org.springframework.transaction.interceptor.TransactionAspectSupport#cleanupTransactionInfoprotectedvoidcleanupTransactionInfo(@NullableTransactionInfotxInfo) {
if (txInfo!=null) {
txInfo.restoreThreadLocalStatus();
   }
}

它的作用其实就是将 ThreadLocal 中保存的当前事务的信息恢复到当前事务开启之前的状态。

commitTransactionAfterReturning 方法

最后,commitTransactionAfterReturning方法负责事务的提交。

// org.springframework.transaction.interceptor.TransactionAspectSupport#commitTransactionAfterReturningprotectedvoidcommitTransactionAfterReturning(@NullableTransactionInfotxInfo) {
if (txInfo!=null&&txInfo.getTransactionStatus() !=null) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for ["+txInfo.getJoinpointIdentification() +"]");
      }
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
   }
}

走到这一步,说明前面的流程实行的都很顺利,因此,直接告诉事务管理器提交事务就可以了。

总结

本文通过对 BeanFactoryTransactionAttributeSourceAdvisor 类的分析,了解了 Spring 是如何通过 AOP 来完成事务的管理的,本文的内容需要你对 Spring 的 AOP 的实现原理有一定的了解。

由于本文的重点是 BeanFactoryTransactionAttributeSourceAdvisor 对提供事务管理功能的分析,遇到涉及太多 Spring 的事务抽象相关的内容,没有做介绍,如果你对此感兴趣,可以搜索相关的文章了解其中的细节。

目录
相关文章
|
20天前
|
Java 应用服务中间件 Nacos
Spring Cloud 常用各个组件详解及实现原理(附加源码+实现逻辑图)
Spring Cloud 常用各个组件详解及实现原理(附加源码+实现逻辑图)
31 0
|
23天前
|
监控 数据可视化 安全
一套成熟的Spring Cloud智慧工地平台源码,自主版权,开箱即用
这是一套基于Spring Cloud的智慧工地管理平台源码,具备自主版权,易于使用。平台运用现代技术如物联网、大数据等改进工地管理,服务包括建设各方,提供人员、车辆、视频监控等七大维度的管理。特色在于可视化管理、智能报警、移动办公和分布计算存储。功能涵盖劳务实名制管理、智能考勤、视频监控AI识别、危大工程监控、环境监测、材料管理和进度管理等,实现工地安全、高效的智慧化管理。
|
1月前
|
消息中间件 NoSQL Java
Spring Cloud项目实战Spring Cloud视频教程 含源码
Spring Cloud项目实战Spring Cloud视频教程 含源码
33 1
|
2月前
|
XML 存储 缓存
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache管理器的实战开发指南(修正篇)
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache管理器的实战开发指南(修正篇)
35 0
|
1天前
|
监控 Java 应用服务中间件
Spring Boot 源码面试知识点
【5月更文挑战第12天】Spring Boot 是一个强大且广泛使用的框架,旨在简化 Spring 应用程序的开发过程。深入了解 Spring Boot 的源码,有助于开发者更好地使用和定制这个框架。以下是一些关键的知识点:
13 6
|
2天前
|
Java 应用服务中间件 测试技术
深入探索Spring Boot Web应用源码及实战应用
【5月更文挑战第11天】本文将详细解析Spring Boot Web应用的源码架构,并通过一个实际案例,展示如何构建一个基于Spring Boot的Web应用。本文旨在帮助读者更好地理解Spring Boot的内部工作机制,以及如何利用这些机制优化自己的Web应用开发。
12 3
|
5天前
|
存储 前端开发 Java
Spring Boot自动装配的源码学习
【4月更文挑战第8天】Spring Boot自动装配是其核心机制之一,其设计目标是在应用程序启动时,自动配置所需的各种组件,使得应用程序的开发和部署变得更加简单和高效。下面是关于Spring Boot自动装配的源码学习知识点及实战。
13 1
|
6天前
|
传感器 人工智能 前端开发
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
智慧校园电子班牌,坐落于班级的门口,适合于各类型学校的场景应用,班级学校日常内容更新可由班级自行管理,也可由学校统一管理。让我们一起看看,电子班牌有哪些功能呢?
47 4
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
|
13天前
|
设计模式 安全 Java
【初学者慎入】Spring源码中的16种设计模式实现
以上是威哥给大家整理了16种常见的设计模式在 Spring 源码中的运用,学习 Spring 源码成为了 Java 程序员的标配,你还知道Spring 中哪些源码中运用了设计模式,欢迎留言与威哥交流。
|
18天前
|
存储 缓存 Java
【spring】06 循环依赖的分析与解决
【spring】06 循环依赖的分析与解决
9 1