spring提供了可配置、易扩展的事务处理框架,本文主要从一下几个方面说明spring事务的原理

  • 基本概念
  • 事务配置解析
  • 事务处理过程

基本概念

事务隔离级别

在同时进行多个事务的时候,可能会出现脏读、不可重复读、幻读四种情况,数据库分别有四种隔离级别处理这些情况。Spring中TransactionDefinition定义了事务的隔离级别和传播属性,隔离级别有

  1. ISOLATION_DEFAULT:PlatforTransactionManager默认的隔离级别,也就是数据库默认的隔离级别,下面四中分别对应数据库四中隔离级别
  2. ISOLATION_READ_UNCOMMITED:在另外一个事务未提交的时候可以读取另一个事务中的数据,会出现脏读、不可重复读、幻读,系统开销最小,没有加锁
  3. ISOLATION_READ_COMMITED:在另外一个事务提交之后才可以读取数据,防止了脏读,会出现不可重复读、幻读
  4. ISOLATION_REPEATABLE_READ:防止了脏读、不可重复读(在一个事物读取数据之后,第一个事务提交数据,第一个事务再次读取数据,发现前后不一致),会出现幻读,读不加锁,增删改加锁
  5. ISOLATION_SERIALIZABLE:可以防止脏读、不可重复读、幻读(第一个事务修改涉及到了数据库中全部行,第二个事务向表中插入一行,第一个事务会发现表中还有没有修改的行)

spring事务传播属性

传播属性:定义了多层事务时候的行为,spring的TransactionDefinition定义了7种事务传播行为

  1. PROPAGETION_REQUIRED:如果已经有事务,则使用当前事务,如果没有则新开一个事务
  2. PROPAGETION_SUPPORT:如果已经有事务则事务的执行,如果没有则非事务地执行
  3. PROPAGERION_MANDATORY:如果有事务则支持事务,否则抛出异常
  4. PROPAGETION_REQUIRES_NEW:总是开启一个新的事务,如果已经有事务,则挂起当前事务
  5. PROPAGETION_NOT_SUPPORT:总是非事务执行,如果有事务则挂起
  6. PROPAGETION_NEVER:总是非事务执行,如果有事务则抛出异常
  7. PEOPAGETION_NESTED:嵌套事务(内层事务不影响外层事务,外层事务失败会回滚内层事务),如果有事务,则嵌套在当前事务中执行,如果没有事务则按照PROPAGETION_REQUIRED的方式运行

事务配置解析

spring支持编程式事务,也支持声明式事务,这里以声明式事务的配置为例。

在配置事务管理器的时候配置为使用cglib生成代理

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

上面xml配置的作用

# tx命名空间的处理类
org.springframework.transaction.config.TxNamespaceHandler
# annotation-driven标签的解析类
org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser
# 解析标签annotation-driven的方法
org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer#configureAutoProxyCreator

解析该标签的时候做了以下的事

  1. 注册org.springframework.aop.config.AopConfigUtils#AUTO_PROXY_CREATOR_BEAN_NAME,org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator
  2. 设置InfrastructureAdvisorAutoProxyCreator这个bean对应的属性,proxyTargetClass,exposeProxy
  3. 注册bean:AnnotationTransactionAttributeSource
  4. 注册bean:TransactionInterceptor
  5. 注册bean:TransactionAttributeSourceAdvisor
  6. 注册组合component:CompositeComponentDefinition

上面解析标签的时候注入的这些bean在getBean的时候会起作用,在getBean的时候会判断是否需要返回包装后的bean,也就是org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary方法,找到所有的advisor(顺便完成初始化),然后判断找出所有可以应用到该类的advisor(org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply),然后利用可用的advisor创建proxy(org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy),这个proxy就是原来类的代理,在请求该类的方法的时候是通过代理进行的,在代理中会判断是否有事务,是否需要开启事务

事务处理过程

Spring 事务处理是基于AOP实现的,为事务方法所在类生成一个代理类,在调用事务方法的时候实际会调用代理类的代理方法,这里就是

org.springframework.transaction.interceptor.TransactionInterceptor#invoke

在看spring事务处理流程之前,我们先回顾下直接使用jdbc编程的时候使用事务的流程

  1. 拿到数据库连接
  2. 设置数据库连接为非自动提交
  3. 执行事务操作
  4. 提交事务

spring事务处理的流程也基本相似,只是做了一些封装

  1. 拿到数据库连接,需要判断当前事务的传播级别,有些传播级别需要新的数据库连接开启新的事务
  2. 设置数据库连接为非自动提交
  3. 执行事务操作
  4. 执行事务提交前的一些回调方法,比如:beforeCommit
  5. 提交事务,判断是否有异常,是需要回滚还是提交
  6. 执行事务提交后的一个方法,比如:afterCommit

总结

spring事务在屏蔽了一些繁琐逻辑的同时,也提供了比较好的扩展性,比如支持自定义数据源,自定义事务管理器,而且支持在事务执行前后加入自己的回调用方法。

spring源码 — 五、事务的更多相关文章

  1. spring源码解析--事务篇(前篇)

    对于每一个JAVA程序员,spring应该是再熟悉不过的框架了,它的功能有多强大我就不多说了,既然他有这么强大的功能,是如何实现的呢?这个就需要从他的原理去了解,而最直接了解原理的方式莫过于源码.当然 ...

  2. spring源码分析---事务篇

    上一篇我介绍了spring事务的传播特性和隔离级别,以及事务定义的先关接口和类的关系.我们知晓了用TransactionTemplate(或者直接用底层P的latformTransactionMana ...

  3. Spring源码之事务(一)— TransactionAutoConfiguration自动配置

    总结: 在ConfigurationClassParser#parse()中会对deferredImportSelectorHandler进行处理(在处理@ComponentScan 自己所写@Com ...

  4. Spring源码深度解析之事务

    Spring源码深度解析之事务 目录 一.JDBC方式下的事务使用示例 (1)创建数据表结构 (2)创建对应数据表的PO (3)创建表和实体之间的映射 (4)创建数据操作接口 (5)创建数据操作接口实 ...

  5. Spring 源码学习笔记11——Spring事务

    Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...

  6. [spring源码学习]五-BeanPostProcessor的使用

    一.接口描述 spring提供了一个接口类-BeanPostProcessor,我们叫他:bean的加工器,应该是在bean的实例化过程中对bean做一些包装处理,里边提供两个方法 public in ...

  7. Spring源码分析(二十五)finishRefresh

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 在 Spring 中还提供了 Lifecycle 接口, Lifecy ...

  8. Spring源码分析(十五)获取单例

    本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 之前我们讲解了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例be ...

  9. Spring源码分析(五)获取Document

    摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 这一篇开始进行Document加载了,XmlBeanFactoryRea ...

随机推荐

  1. 利用Python脚本悄无声息的遥控室友电脑开机密码!

    整蛊一下室友就行了,切勿用于非法用途! 利用python脚本控制室友windows系统电脑的开机密码.利用random()生成随机数(密码),天知地知,密码只有你自己知道! Python代码分为cli ...

  2. 二叉树,AVL树和红黑树

    为了接下来能更好的学习TreeMap和TreeSet,讲解一下二叉树,AVL树和红黑树. 1. 二叉查找树 2. AVL树 2.1. 树旋转 2.1.1. 左旋和右旋 2.1.2. 左左,右右,左右, ...

  3. Gradle连接Maven仓库直接从仓库 更新JAR包

    一般情况下服务器编写好服务程序  会用Maven打成JAR包,放在Maven仓库里管理,我们在用的时候直接引用就可以, 那么如何在Gradle项目中使用本地的  或者远程的Maven仓库呢    当M ...

  4. 树莓派配置watchdog

    安装watchdog apt install watchdog 编辑/etc/modules,添加bcm2708_wdog 编辑/etc/watchdog.conf watchdog-device = ...

  5. Flask构建微电影(一)

    第一章.项目介绍  1.1.前言    本教程我将带领大家如何使用flask框架开发微电影网站.Flask是python中最受欢迎的轻量级web框架,flask扩展丰富,冗余度小,可自由选择组合各种插 ...

  6. MySQL SHOW TABLE 输出的每列详细介绍

    Name: 表名 Engine: 表的存储引擎(旧版本中,该值为Type) Row_format: 行的格式.对于MyISAM表,可选的值为Dynamic.Fixed或者Copressed. Dyna ...

  7. 微信小游戏开发Canvas资源汇总

    Demo: 微信小程序demo组件:股票分时图 微信小程序小组件:仿直播点赞气泡效果,基于Canvas 优质demo推荐:二维码生成器:使用canvas与纯JS版二维码生成 微信小程序学习用完整dem ...

  8. node npm --save,不同JS解析器的内置全局变量,PROMISE,CONST---ES6

    npm  --save 当你为你的模块安装一个依赖模块时,正常情况下你得先安装他们(在模块根目录下npm install module-name),然后连同版本号手动将他们添加到模块配置文件packa ...

  9. nginx配置SSL实现服务器/客户端双向认证

    http://blog.csdn.net/kunoy/article/details/8239653 本人不才,配置了两天,终于搞出来了,结合网上诸多博文,特此总结一下! 配置环境: Ubuntu 1 ...

  10. QM4_Probability

    Basic Concepts Probability concepts Terms Random variable A quantity whose possible values are uncer ...