• spring源码 — 五、事务


    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事务

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

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

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

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

    总结

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

  • 相关阅读:
    Docker容器启动时初始化Mysql数据库
    使用Buildpacks高效构建Docker镜像
    Mybatis 强大的结果集映射器resultMap
    Java 集合排序策略接口 Comparator
    Spring MVC 函数式编程进阶
    换一种方式编写 Spring MVC 接口
    【asp.net core 系列】6 实战之 一个项目的完整结构
    【asp.net core 系列】5 布局页和静态资源
    【asp.net core 系列】4. 更高更强的路由
    【Java Spring Cloud 实战之路】- 使用Nacos和网关中心的创建
  • 原文地址:https://www.cnblogs.com/sunshine-2015/p/10562202.html
Copyright © 2020-2023  润新知