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


相关文章
|
5天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
18 2
|
22天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
14天前
|
Java 开发者 Spring
Spring高手之路24——事务类型及传播行为实战指南
本篇文章深入探讨了Spring中的事务管理,特别是事务传播行为(如REQUIRES_NEW和NESTED)的应用与区别。通过详实的示例和优化的时序图,全面解析如何在实际项目中使用这些高级事务控制技巧,以提升开发者的Spring事务管理能力。
27 1
Spring高手之路24——事务类型及传播行为实战指南
|
7天前
|
XML Java 数据库连接
Spring中的事务是如何实现的
Spring中的事务管理机制通过一系列强大的功能和灵活的配置选项,为开发者提供了高效且可靠的事务处理手段。无论是通过注解还是AOP配置,Spring都能轻松实现复杂的事务管理需求。掌握这些工具和最佳实践,能
13 3
|
11天前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
37 9
|
1月前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
37 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
1月前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
111 5
|
6月前
|
Java 关系型数据库 数据库连接
Spring源码解析--深入Spring事务原理
本文将带领大家领略Spring事务的风采,Spring事务是我们在日常开发中经常会遇到的,也是各种大小面试中的高频题,希望通过本文,能让大家对Spring事务有个深入的了解,无论开发还是面试,都不会让Spring事务成为拦路虎。
95 1
|
1月前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
1月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
127 9