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

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

4.1.1:doGetTransaction获取事务对象 doGetTransaction的实现在DataSourceTransactionManager中,doGetTransactiond创建一个DataSourceTransactionObject用于表示事务。并尝试获取一个与当前线程关联的Connection,这一部分工作交给事务同步管理器TransactionSynchronizationManager来完成。核心在doGetResource方法上。


private static final ThreadLocal<Map<Object, Object>> resources =
      new NamedThreadLocal<Map<Object, Object>>("Transactional resources");
private static Object doGetResource(Object actualKey) {
    Map<Object, Object> map = resources.get();
    if (map == null) {
      return null;
    }
    Object value = map.get(actualKey);
    // Transparently remove ResourceHolder that was marked as void...
    if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
      map.remove(actualKey);
      // Remove entire ThreadLocal if empty...
      if (map.isEmpty()) {
        resources.remove();
      }
      value = null;
    }
    return value;
  }

以当前Datasoure对象为key ,从ThreadLocal对象resources中获取Connection


4.1.2:没有事务属性创建一个事务属性


4.1.3:判断当前是否有事务存在(重点) 默认是false,子类可以重写isExistingTransaction方法。DataSourceTransactionManager中重写了此方法


@Override
  protected boolean isExistingTransaction(Object transaction) {
    DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
    return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
  }

查看事务对象获取的Connectin是否为空,Connection是否活跃。是否存在事务指:当前线程中是否存在以当前数据源为key的获取连接Connection.


4.1.3.1:

handleExistingTransaction(处理当前有事务的情况) 事务的传播属性处理

  • NEVER: 不支持当前事务,因为当前有事务,抛出异常
  • NOT_SUPPORTED:不支持当前事务,当前有事务存在,就挂起当前事务。所谓的suspend(transaction)挂起在代码里的表现是:(1)将当前是我的ConnectionHolder设置为null(2)从ThreadLocal对象resources中移除当前线程的Connection(3)将事务的挂起状态封装到SuspendedResourcesHolder中设置到TransactionStatus中,返回。
  • REQUIRES_NEW:挂起当前事务,创建新事务。suspend(transaction)挂起,doBegin(transaction, definition)创建新事务;
  • NESTED:嵌套事务。分为非JTA事务与JTA事务。JTA事务创建doBegin(transaction, definition)创建新事务
  • SUPPORTS/REQUIRED/MANDATORY: 不处理


4.1.4: 校验超时


4.1.5:处理当前没有事务的情况

  • MANDATORY: 支持当前事务,当前事务没有,则抛出异常
  • REQUIRED/REQUIRES_NEW/NESTED:  创建新事务doBegin(transaction, definition)
  • NOT_SUPPORTED/SUPPORTS/NEVER:  只是打印warn日志。隔离无意义。


事务创建 doBegin

  1. 事务里没有数据库连接Connection,则从dataSource里获取一个
  2. 设置隔离级别
  3. 设置数据库自动提交为false
  4. 把Connection放到ThreadLocal对象resources中


至此:getTransaction 返回一个封装了事务的TransactionStatus对象。 总结下:getTransaction 方法重要点

  • 获取数据连接,
  • 处理spring事务传播方式
  • 设置自动提交为false

4.2prepareTransactionInfo方法

prepareTransactionInfo方法主要是封装:事务管理器PlatformTransactionManager对象,TransactionAttribute事务属性对象,方法名


joinpointIdentificationTransactionStatus对象 成一TransactionInfo对象。并把TransactionInfo对象通过bindToThread()方法绑定到ThreadLocal<TransactionInfo> transactionInfoHolder

至此: createTransactionIfNecessary完成,得到一个TransactionInfo对象。


5.invocation.proceedWithInvocation();

执行下一个增强。在没其他增强的情况下,这通常会导致调用目标对象。


6.completeTransactionAfterThrowing

在目标方法执行错误的情况下,catch异常,执行回滚。 核心在DataSourceTransactionManager.doRollback方法


Connection con = txObject.getConnectionHolder().getConnection();
    if (status.isDebug()) {
      logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
    }
    try {
      con.rollback();
    }


7.cleanupTransactionInfo(txInfo)

finally 一定执行,清除事务信息。 其实就是把ThreadLocal transactionInfoHolder里的新事务信息清除掉。设置为原事务信息


8.commitTransactionAfterReturning(txInfo);

提交事务 核心在DataSourceTransactionManager.doCommit方法

Connection con = txObject.getConnectionHolder().getConnection();
    if (status.isDebug()) {
      logger.debug("Committing JDBC transaction on Connection [" + con + "]");
    }
    try {
      con.commit();
    }

至此整个事务执行原理完成。里面涉及到很多细节,由于篇幅的原因不能一一列出。建议多看代码。


总结


事务代理的执行,其实就是在AOP基础上的建立起来的。

关键是理解TransactionInterceptor(Advice)。在目标方法执行前后对其进行事务控制的增强。


相关文章
|
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
|
监控 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》以提升面试表现。更多技术资料可在公众号【技术自由圈】获取。
|
Java Spring
Spring Boot 中的事务传播行为是什么,原理,如何使用
Spring Boot 中的事务传播行为是什么,原理,如何使用