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. Hadoop生态圈初识

    一.简介 Hadoop是一个由Apache基金会所开发的分布式系统基础架构.Hadoop的框架最核心的设计就是:HDFS和MapReduce.HDFS为海量的数据提供了存储,则MapReduce为海量 ...

  2. 网络-udp

    1. 网络:把双方或者多方的设备(电脑,智能手机,ipad等)连接起来的一个工具     1.1 学习网络的目的: 通过网络把数据从一方传递到另外一方,完成数据的共享 2. ip地址     2.1: ...

  3. .NET之EntityFramework框架运用

    1.创建EF模型库 创建类库-->添加新建项-->选择ADO.NET实体数据模型-->选择 来自数据库的EF选择器-->配置数据库链接以及相应的数据库-->看底部(将ap ...

  4. pycharm的安装及用法

    俗话说的好:"工欲善其事,必先利其器",程序员写代码,肯定不能在编译器里面写,这有一个全宇宙最好的python编译器,叫做pycharm ,他的优点呢,大家可以看一下: 优点:1, ...

  5. List数组和集合相互转换

    1.List的toArray()方法用于将集合转换成数组,但实际上改方法是在Collection中定义的,所以所有的集合都具备这个功能, 其有两个方法:Object[] toArray()  和   ...

  6. 页面读取Excel

    var input = document.getElementById("file");    //支持chrome IE10    if (window.FileReader) ...

  7. capwap学习笔记——初识capwap(五)(转)

    3. CAPWAP Binding for IEEE 802.11 ¢ CAPWAP协议本身并不包括任何指定的无线技术.它依靠绑定协议来扩展对特定无线技术的支持. ¢ RFC5416就是用来扩展CAP ...

  8. Elasticsearch结构化搜索_在案例中实战使用term filter来搜索数据

    1.根据用户ID.是否隐藏.帖子ID.发帖日期来搜索帖子 (1)插入一些测试帖子数据 POST /forum/article/_bulk { "index": { "_i ...

  9. JavaScript设计模式 Item 3 --封装

    在JavaScript 中,并没有对抽象类和接口的支持.JavaScript 本身也是一门弱类型语言.在封装类型方面,JavaScript 没有能力,也没有必要做得更多.对于JavaScript 的设 ...

  10. 如何把Python脚本导出为exe程序

    一.pyinstaller简介 pyinstaller将Python脚本打包成可执行程序,使在没有Python环境的机器上运行 最新版是pyinstaller 3.1.1.支持python2.7和py ...