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)。在目标方法执行前后对其进行事务控制的增强。


相关文章
|
7月前
|
SQL Java 关系型数据库
Spring事务传播机制:7种姿势教你玩转"事务接力赛"
事务传播机制是Spring框架中用于管理事务行为的重要概念,它决定了在方法调用时事务如何传递与执行。通过7种传播行为,开发者可以灵活控制事务边界,适应不同业务场景。例如:REQUIRED默认加入或新建事务,REQUIRES_NEW独立开启新事务,NESTED支持嵌套回滚等。合理使用传播机制不仅能保障数据一致性,还能提升系统性能与健壮性。掌握这“七种人格”,才能在复杂业务中游刃有余。
|
8月前
|
Java 关系型数据库 数据库
深度剖析【Spring】事务:万字详解,彻底掌握传播机制与事务原理
在Java开发中,Spring框架通过事务管理机制,帮我们轻松实现了这种“承诺”。它不仅封装了底层复杂的事务控制逻辑(比如手动开启、提交、回滚事务),还提供了灵活的配置方式,让开发者能专注于业务逻辑,而不用纠结于事务细节。
1092 1
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
654 70
|
8月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
11月前
|
人工智能 Java 数据库连接
Spring事务失效场景
本文深入探讨了Spring框架中事务管理可能失效的几种常见场景及解决方案,包括事务方法访问级别不当、方法内部自调用、错误的异常处理、事务管理器或数据源配置错误、数据库不支持事务以及不合理的事务传播行为或隔离级别。通过合理配置和正确使用`@Transactional`注解,开发者可以有效避免这些问题,确保应用的数据一致性和完整性。
967 10
|
10月前
|
Java 关系型数据库 MySQL
【Spring】【事务】初学者直呼学会了的Spring事务入门
本文深入解析了Spring事务的核心概念与使用方法。Spring事务是一种数据库事务管理机制,通过确保操作的原子性、一致性、隔离性和持久性(ACID),维护数据完整性。文章详细讲解了声明式事务(@Transactional注解)和编程式事务(TransactionTemplate、PlatformTransactionManager)的区别与用法,并探讨了事务传播行为(如REQUIRED、REQUIRES_NEW等)及隔离级别(如READ_COMMITTED、REPEATABLE_READ)。
735 1
|
9月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
1298 0
|
10月前
|
人工智能 Java 测试技术
Spring Boot 集成 JUnit 单元测试
本文介绍了在Spring Boot中使用JUnit 5进行单元测试的常用方法与技巧,包括添加依赖、编写测试类、使用@SpringBootTest参数、自动装配测试模块(如JSON、MVC、WebFlux、JDBC等),以及@MockBean和@SpyBean的应用。内容实用,适合Java开发者参考学习。
1114 0

热门文章

最新文章

下一篇
开通oss服务