springboot中事务的源码分析(一)

1,048 阅读2分钟

今天我带领大家一起看一下springboot中,事务怎么使用以及源码解析:

springboot事务生效

@EnableTransactionManagement一切的起源

image.png

不懂springboot自动装配的可以给我留言,我会讲一下,这里我就不再叙述了,我就当大家都懂了,我们就先从@EnableTransactionManagement这个注解开始一个愉快的旅程:

image.png

TransactionManagementConfigurationSelector这个类继承了importSeletor接口(如果想了解importSeletor接口的留言), 默认情况下走PROXY的逻辑:

image.png

ProxyTransactionManagementConfiguration主要干了三件事(实现原理AOP):

  • 注入BeanFactoryTransactionAttributeSourceAdvisor类,这个类是advisor,继承了 AbstractBeanFactoryPointcutAdvisor,需要提供PointCut和MethodInterceptor.
  • 注入AnnotationTransactionAttributeSource主要来获取事务的源信息,底层就是通过解析@Transactional注解
  • 注入TransactionInterceptor,这个类主要继承了MethodInterceptor,是事务的关键

image.png

我们重点类说BeanFactoryTransactionAttributeSourceAdvisor和TransactionInterceptor

1、先说BeanFactoryTransactionAttributeSourceAdvisor

image.png

TransactionAttributeSourcePointcut继承了StaticMethodMatcherPointcut(其实切入点方式有六种)

image.png 主要看matches方法: 我们来追溯一下这个getTransactionAttribute方法:到这个 AbstractFallbackTransactionAttributeSource类中,当中有两个抽象方法:

@Nullable
//通过类获取事务信息
protected abstract TransactionAttribute findTransactionAttribute(Class<?> clazz);

/**
 * Subclasses need to implement this to return the transaction attribute for the
 * given method, if any.
 * @param method the method to retrieve the attribute for
 * @return all transaction attribute associated with this method, or {@code null} if none
 */
@Nullable
//通过方法获取事务信息
protected abstract TransactionAttribute findTransactionAttribute(Method method);

这两个方法的实现在AnnotationTransactionAttributeSource,当初ProxyTransactionManagementConfiguration注入的就是这个类,最终我们看到了 SpringTransactionAnnotationParser image.png 进入SpringTransactionAnnotationParser的parseTransactionAnnotation方法:

image.png 就是判断从类或方法中的@Transactional注解中拿到的信息是否为null.

2、TransactionInterceptor这个类是事务的主要实现

image.png 进去invokeWithinTransaction方法,看主要逻辑

//先获取事务管理器,PlatformTransactionManager是接口,我这里的实现类是DataSourceTransactionManager
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
   // 创建一个TransactionInfo实例
   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 {
      cleanupTransactionInfo(txInfo);
   }

   if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
      // Set rollback-only in case of Vavr failure matching our rollback rules...
      TransactionStatus status = txInfo.getTransactionStatus();
      if (status != null && txAttr != null) {
         retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
      }
   }

   commitTransactionAfterReturning(txInfo);
   return retVal;
}

详细看一下这个环绕通知的几个方法

  • createTransactionIfNecessary
  • completeTransactionAfterThrowing
  • cleanupTransactionInfo
  • commitTransactionAfterReturning

createTransactionIfNecessary

image.png

image.png

上述的代码是创建transationinfo的过程,接下来操作都是transationinfo这个对象、

completeTransactionAfterThrowing

image.png

cleanupTransactionInfo

image.png

image.png

commitTransactionAfterReturning

image.png

后面我会跟大家来聊一下事务管理器的源码