返回介绍

10.3 事务增强器

发布于 2025-04-22 22:09:16 字数 4115 浏览 0 评论 0 收藏 0

TransactionInterceptor 支撑着整个事务功能的架构,逻辑还是相对复杂的,那么现在我们切入正题来分析此拦截器是如何实现事务特性的。TransactionInterceptor 类继承自 MethodInterceptor,所以调用该类是从其 invoke 方法开始的,首先预览下这个方法:

public Object invoke(final MethodInvocation invocation) throws Throwable {

  Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass

  (invocation.getThis()) : null);

 //获取对应事务属性

  final TransactionAttribute txAttr =

 getTransactionAttributeSource().getTransactionAttribute (invocation.

  getMethod(), targetClass);

//获取 beanFactory 中的 transactionManager

final PlatformTransactionManager tm = determineTransactionManager(txAttr);

//构造方法唯一标识(类.方法,如 service.UserServiceImpl.save)

final String joinpointIdentification = methodIdentification (invocation.

getMethod(), targetClass);

 //声明式事务处理

  if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransaction

  Manager)) {

  //创建 TransactionInfo

   TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpoint

  Identification);

   Object retVal = null;

   try {

   //执行被增强方法

    retVal = invocation.proceed();

  }

   catch (Throwable ex) {

   //异常回滚

    completeTransactionAfterThrowing(txInfo, ex);

    throw ex;

  }

   finally {

   //清除信息

   cleanupTransactionInfo(txInfo);

  }

  //提交事务

  commitTransactionAfterReturning(txInfo);

   return retVal;

 }

  else {

  //编程式事务处理

   try {

    Object result = ((CallbackPreferringPlatformTransactionManager) tm).

   execute(txAttr,

    new TransactionCallback<Object>() {

     public Object doInTransaction(TransactionStatus status) {

      TransactionInfo txInfo = prepareTransactionInfo(tm,

      txAttr, joinpointIdentification, status);

       try {

        return invocation.proceed();

      }

       catch (Throwable ex) {

        if (txAttr.rollbackOn(ex)) {

         // A RuntimeException: will lead to a rollback.

         if (ex instanceof RuntimeException) {

          throw (RuntimeException) ex;

        }

         else {

          throw new ThrowableHolderException(ex);

        }

       }

        else {

         // A normal return value: will lead to a commit.

         return new ThrowableHolder(ex);

       }

      }

       finally {

       cleanupTransactionInfo(txInfo);

      }

     }

    });

    // Check result: It might indicate a Throwable to rethrow.

    if (result instanceof ThrowableHolder) {

     throw ((ThrowableHolder) result).getThrowable();

   }

    else {

     return result;

   }

  }

   catch (ThrowableHolderException ex) {

    throw ex.getCause();

  }

 }

}

从上面的函数中,我们尝试整理下事务处理的脉络,在 Spring 中支持两种事务处理的方式,分别是声明式事务处理与编程式事务处理,两者相对于开发人员来讲差别很大,但是对于 Spring 中的实现来讲,大同小异。在 invoke 中我们也可以看到这两种方式的实现。考虑到对事务的应用比声明式的事务处理使用起来方便,也相对流行些,我们就以此种方式进行分析。对于声明式的事务处理主要有以下几个步骤。

(1)获取事务的属性。

对于事务处理来说,最基础或者说最首要的工作便是获取事务属性了,这是支撑整个事务功能的基石,如果没有事务属性,其他功能也无从谈起,在分析事务准备阶段时我们已经分析了事务属性提取的功能,大家应该有所了解。

(2)加载配置中配置的 TransactionManager。

(3)不同的事务处理方式使用不同的逻辑。

对于声明式事务的处理与编程式事务的处理,第一点区别在于事务属性上,因为编程式的事务处理是不需要有事务属性的,第二点区别就是在 TransactionManager 上,CallbackPreferring PlatformTransactionManager 实现 PlatformTransactionManager 接口,暴露出一个方法用于执行事务处理中的回调。所以,这两种方式都可以用作事务处理方式的判断。

(4)在目标方法执行前获取事务并收集事务信息。

事务信息与事务属性并不相同,也就是 TransactionInfo 与 TransactionAttribute 并不相同, TransactionInfo 中包含 TransactionAttribute 信息,但是,除了 TransactionAttribute 外还有其他事务信息,例如 PlatformTransactionManager 以及 TransactionStatus 相关信息。

(5)执行目标方法。

(6)一旦出现异常,尝试异常处理。

并不是所有异常,Spring 都会将其回滚,默认只对 RuntimeException 回滚。

(7)提交事务前的事务信息清除。

(8)提交事务。

上面的步骤分析旨在让大家对事务功能与步骤有个大致的了解,具体的功能还需要详细地分析。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。