spring源码系列11:事务代理对象的执行(上)

简介: spring源码系列11:事务代理对象的执行(上)

回顾


spring源码系列9:事务代理的创建一节, 事务通过定义

  • 切点: TransactionAttributeSourcePointcut 、
  • 通知(拦截器) TransactionInterceptor
  • Advisor:  BeanFactoryTransactionAttributeSourceAdvisor
    在AOP基础上实现事务代理的功能

spring源码系列10:AOP代理对象的执行一节。 总结出,不管是AOP-JDK代理还是CGLB动态代理,都会执行Advice完成增强功能。

也就是说:事务的核心功能就在这个TransactionInterceptor


事务执行


TransactionInterceptor

@Override
  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();
      }
    });
  }

交给父类TransactionAspectSupport.invokeWithinTransaction()去执行


TransactionAspectSupport

invokeWithinTransaction方法比较长,我们看前半部分。

protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
      throws Throwable {
    // If the transaction attribute is null, the method is non-transactional.
    1.
    final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
    2.
    final PlatformTransactionManager tm = determineTransactionManager(txAttr);
    3.
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
    if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
      // Standard transaction demarcation with getTransaction and commit/rollback calls.
      4.
      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.
        5.
        retVal = invocation.proceedWithInvocation();
      }
      catch (Throwable ex) {
        // target invocation exception
        6.
        completeTransactionAfterThrowing(txInfo, ex);
        throw ex;
      }
      finally {
      7.
        cleanupTransactionInfo(txInfo);
      }
      8.
      commitTransactionAfterReturning(txInfo);
      return retVal;
    }
    ... 
  }


1.拿到事务属性TransactionAttribute :

我们使用注解@Transactional时,注解元信息会被包装成TransactionAttribute ,此处拿到的就是@Transactional的元数据


2.determineTransactionManager(txAttr)

找到一个合适的事务管理器

protected PlatformTransactionManager determineTransactionManager(TransactionAttribute txAttr) {
    // Do not attempt to lookup tx manager if no tx attributes are set
    //未设置事务属性,也没有设置beanFactory ,直接返回
    if (txAttr == null || this.beanFactory == null) {
      return getTransactionManager();
    }
    //如果@Transactional 指定了具体事务管理器,则根据beanname去容器中找到他
    String qualifier = txAttr.getQualifier();
    if (StringUtils.hasText(qualifier)) {
      return determineQualifiedTransactionManager(qualifier);
    }
    //如果是TransactionAspectSupport.transactionManagerBeanName指定了具体事务管理器,
    //beanname去容器中找
    else if (StringUtils.hasText(this.transactionManagerBeanName)) {
      return determineQualifiedTransactionManager(this.transactionManagerBeanName);
    }
    //没有beanName指定具体的事务管理器Bean。
    /**
    1.查看transactionManager属性是否设置事务管理器对象
    2.查看事务管理器缓存中有没有
    3.去容器中寻找,找PlatformTransactionManager接口的实现类。getBean(PlatformTransactionManager),
    找到放到事务管理器缓存中。
    **/
    else {
      PlatformTransactionManager defaultTransactionManager = getTransactionManager();
      if (defaultTransactionManager == null) {
        defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
        if (defaultTransactionManager == null) {
          defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);
          this.transactionManagerCache.putIfAbsent(
              DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
        }
      }
      return defaultTransactionManager;
    }
  }

以集成了DataSourceTransactionManager为例。determineTransactionManager返回的就是DataSourceTransactionManager对象。


3.methodIdentification方法

获取目标方法全名


4.createTransactionIfNecessary开启事务重点

protected TransactionInfo createTransactionIfNecessary(
      PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {
    // If no name specified, apply method identification as transaction name.
    如果事务名称没有指定,则使用方法名作为事务名
    if (txAttr != null && txAttr.getName() == null) {
      txAttr = new DelegatingTransactionAttribute(txAttr) {
        @Override
        public String getName() {return joinpointIdentification;}
      };
    }
    ...
    TransactionStatus status = tm.getTransaction(txAttr);
    ...
    return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
  }


重点在

  • getTransaction方法获取TransactionStatus 事务
  • prepareTransactionInfo方法上,封装一个TransactionInfo
4.1:getTransaction ()

getTransaction ()是一个模板方法,PlatformTransactionManager定义了getTransaction 方法。抽象类AbstractPlatformTransactionManager实现了getTransaction 方法。因为是模板方法。方法内很多方法都是在具体的PlatformTransactionManager实现的。(本文以DataSourceTransactionManager为例)


public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
    1.尝试获取事务对象,并封装当前线程中以当前datasource为key的Connection。
    Object transaction = doGetTransaction();
    2.没有配置事务属性,则创建一个默认的事务属性
    if (definition == null) {
      // Use defaults if no transaction definition given.
      definition = new DefaultTransactionDefinition();
    }
    3.判断是否有已经存在是否:判断条件是当前线程有Connection.并且Connection是活跃的
    if (isExistingTransaction(transaction)) {
      // Existing transaction found -> check propagation behavior to find out how to behave.
      已存在事务,则处理传播属性,然后返回。(处理两个事务之间的传播属性关系)
      return handleExistingTransaction(definition, transaction, debugEnabled);
    }
    ===========当前没有事务
    // Check definition settings for new transaction.
    4.超时时间校验
    if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
      throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
    }
    5.开始处理当前事务
    // No existing transaction found -> check propagation behavior to find out how to proceed.
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
      throw new IllegalTransactionStateException(
          "No existing transaction found for transaction marked with propagation 'mandatory'");
    }
    else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
        definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
        definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
      SuspendedResourcesHolder suspendedResources = suspend(null);
      if (debugEnabled) {
        logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
      }
      try {
        boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
        DefaultTransactionStatus status = newTransactionStatus(
            definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
        doBegin(transaction, definition);
        prepareSynchronization(status, definition);
        return status;
      }
      catch (RuntimeException ex) {
        resume(null, suspendedResources);
        throw ex;
      }
      catch (Error err) {
        resume(null, suspendedResources);
        throw err;
      }
    }
    else {
      // Create "empty" transaction: no actual transaction, but potentially synchronization.
      if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
        logger.warn("Custom isolation level specified but no actual transaction initiated; " +
            "isolation level will effectively be ignored: " + definition);
      }
      boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
      return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
    }
  }

下面拆解此方法


相关文章
|
2月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
6月前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
399 70
|
7月前
|
存储 监控 数据可视化
SaaS云计算技术的智慧工地源码,基于Java+Spring Cloud框架开发
智慧工地源码基于微服务+Java+Spring Cloud +UniApp +MySql架构,利用传感器、监控摄像头、AI、大数据等技术,实现施工现场的实时监测、数据分析与智能决策。平台涵盖人员、车辆、视频监控、施工质量、设备、环境和能耗管理七大维度,提供可视化管理、智能化报警、移动智能办公及分布计算存储等功能,全面提升工地的安全性、效率和质量。
127 0
|
9月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
320 7
|
监控 Java 数据库
Spring事务相关配置、案例:转账业务追加日志及事务传播行为
Spring事务相关配置、案例:转账业务追加日志及事务传播行为
160 0
|
存储 Java 数据库
Spring事务和事务传播机制
Spring事务和事务传播机制
146 0
|
11月前
|
Java 开发者 Spring
Spring高手之路24——事务类型及传播行为实战指南
本篇文章深入探讨了Spring中的事务管理,特别是事务传播行为(如REQUIRES_NEW和NESTED)的应用与区别。通过详实的示例和优化的时序图,全面解析如何在实际项目中使用这些高级事务控制技巧,以提升开发者的Spring事务管理能力。
261 1
Spring高手之路24——事务类型及传播行为实战指南
|
10月前
|
Java 关系型数据库 数据库
京东面试:聊聊Spring事务?Spring事务的10种失效场景?加入型传播和嵌套型传播有什么区别?
45岁老架构师尼恩分享了Spring事务的核心知识点,包括事务的两种管理方式(编程式和声明式)、@Transactional注解的五大属性(transactionManager、propagation、isolation、timeout、readOnly、rollbackFor)、事务的七种传播行为、事务隔离级别及其与数据库隔离级别的关系,以及Spring事务的10种失效场景。尼恩还强调了面试中如何给出高质量答案,推荐阅读《尼恩Java面试宝典PDF》以提升面试表现。更多技术资料可在公众号【技术自由圈】获取。