6

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

 3 years ago
source link: http://sunliangliang.com/?p=53
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

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

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

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

1.AOP代理流程

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

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

  • TransactionInterceptorinvoke方法作为入口执行
    • 获取代理对象
    • 执行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)

更多内容可关注公众号


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK