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


相关文章
|
1月前
|
XML 缓存 Java
Spring源码之 Bean 的循环依赖
循环依赖是 Spring 中经典问题之一,那么到底什么是循环依赖?简单说就是对象之间相互引用, 如下图所示: 代码层面上很好理解,在 bean 创建过程中 class A 和 class B 又经历了怎样的过程呢? 可以看出形成了一个闭环,如果想解决这个问题,那么在属性填充时要保证不二次创建 A对象 的步骤,也就是必须保证从容器中能够直接获取到 B。 一、复现循环依赖问题 Spring 中默认允许循环依赖的存在,但在 Spring Boot 2.6.x 版本开始默认禁用了循环依赖 1. 基于xml复现循环依赖 定义实体 Bean java复制代码public class A {
|
1月前
|
监控 Java 数据处理
【Spring云原生】Spring Batch:海量数据高并发任务处理!数据处理纵享新丝滑!事务管理机制+并行处理+实例应用讲解
【Spring云原生】Spring Batch:海量数据高并发任务处理!数据处理纵享新丝滑!事务管理机制+并行处理+实例应用讲解
|
1月前
|
Java 测试技术 数据库连接
【Spring源码解读!底层原理高级进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨
【Spring源码解读!底层原理高级进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨
|
5天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
11天前
|
Java Spring
玩转对象掌控权:深入Spring,精准控制对象创建次数
玩转对象掌控权:深入Spring,精准控制对象创建次数
14 0
|
11天前
|
Java 关系型数据库 MySQL
高级对象装配:解析Spring创建复杂对象的秘诀
高级对象装配:解析Spring创建复杂对象的秘诀
26 0
高级对象装配:解析Spring创建复杂对象的秘诀
|
1月前
|
Java Spring
使用spring实现邮件的发送(含测试,源码,注释)
使用spring实现邮件的发送(含测试,源码,注释)
7 0
|
1月前
|
XML Java 数据库
【二十四】springboot整合spring事务详解以及实战
【二十四】springboot整合spring事务详解以及实战
101 0
|
1月前
|
Java Spring 容器
【Spring源码】单例创建期间进行同步可能会导致死锁?
通过这个标题我们就可以思考本次的阅读线索了,看起来可以学到不少东西。1. 旧代码的死锁是怎么产生的。2. 贡献者通过改变什么来解决本次PR的问题呢?而阅读线索2的答案也显而易见,就是上文提到的通过后台线程来创建Micrometer单例...
41 3
|
6月前
|
Java Spring
【Spring事务的实现原理】
【Spring事务的实现原理】

热门文章

最新文章