暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

02.Spring事务的源码(一):入口类以及核心主流程

阿亮的日志 2021-04-14
663

探寻Spring事务的入口类以及核心主流程

前言

基础知识已经了解完毕,本篇主要讲解下Spring对于事务支持的源码。从入口类到主流程

我们通过一个简单的@Transactional
的注解就完成了对于事务的支持。这里面的内部的构造大家也都知道是通过AOP
的思想来实现的,那么到底是如何处理的,我们来一探究竟。

知识点

  • 事务的处理流程:Aop代理实现
  • 事务处理的入口类:TransactioanIntercepor
  • 事务的核心主流程:事务开启->执行业务流程 ?执行成功:提交事务,执行失败:回滚事务

1.AOP代理流程

Spring对于事务的管理,是用Aop来实现的。通过添加@Transational注解实现 事务的管理通过TransactionManager
来处理

这里我们可以先通过一张图基于我们目前的知识对spring事务的基本流程有个印象。

  • TransactionInterceptor
    invoke
    方法作为入口执行
    • 获取代理对象
    • 开启事务
    • 执行service的业务逻辑
    • 若出现异常则,回滚事务
    • 若执行成功,提交事务

2.Spring事务源码初探

2.1.入口类TransactioanIntercepor

TransactioanIntercepor
会对我们添加了@Transactional
注解的方法或者类进行拦截,之后就会在执行业务逻辑之前先调用该类。我们假设有一个流量充值的功能。代码片段如下:

  @Transactional
  public void finishRefillData(RefillRequest refillRequest) {
    // 完成支付转账
    accountAmountService.transfer(refillRequest.getUserAccountId(),
        refillRequest.getBusinessAccountId(), refillRequest.getPayAmount());
    // 创建充值订单
    refillOrderService.add(createRefillOrder(refillRequest));
  }

基于上面的代码片段,我们来研究下源码的执行流程。

2.2.执行流程

找到了入口类TransactioanIntercepor
之后,我们可以找到如下代码

1.TransactioanIntercepor.invoke()

public Object invoke(final 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 InvocationCallback() {
  @Override
  public Object proceedWithInvocation() throws Throwable {
   return invocation.proceed();
  }
 });
}

这里的targetClass
即为我们注解@Transactional
标注的类RefillDataCenterServiceImpl
,核心的业务逻辑都在invokeWithinTransaction()
方法中

2.TransactionAspectSupport.invokeWithinTransaction

通过类名xxxAspectxxx
我们可以看出这是一个Aop的代理类。

下面这段逻辑是核心,包含了事务的开启,提交,回滚等。

protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
  throws Throwable 
{

 // If the transaction attribute is null, the method is non-transactional.
 final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
 //这里是JTATransactionManager
 final PlatformTransactionManager tm = determineTransactionManager(txAttr);
 //这里是RefillDataCenterServiceImpl的全限定名
 final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

 if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
  // Standard transaction demarcation with getTransaction and commit/rollback calls.
  //事务是在这里开始创建的
  TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
  Object retVal = null;
  try {
   // This is an around advice: Invoke the next interceptor in the chain.
   // This will normally result in a target object being invoked.
   //这里执行我们具体的业务方法,即`RefillDataCenterService.finishRefillData()`
   retVal = invocation.proceedWithInvocation();
  }
  catch (Throwable ex) {
   // target invocation exception
   //如果上面的业务逻辑代码报错了,这里进行事务的回滚
   completeTransactionAfterThrowing(txInfo, ex);
   throw ex;
  }
  finally {
   cleanupTransactionInfo(txInfo);
  }
  //如果没有报错,这里进行事务的提交
  commitTransactionAfterReturning(txInfo);
  return retVal;
 }

  • 1.创建事务:
    • TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
  • 2.执行业务逻辑:
    • invocation.proceedWithInvocation()
  • 3.若执行业务失败:回滚事务
    • completeTransactionAfterThrowing(txInfo, ex)
  • 4.若业务执行成功:事务提交
    • commitTransactionAfterReturning(txInfo)

关于

更多内容可关注公众号

  • Github: https://github.com/liangliang1259/common-notes
  • 公众号


文章转载自阿亮的日志,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论