spring 提供了可配置, 易扩展的事务处理框架, 本文主要从一下几个方面说明 spring 事务的原理
基本概念
事务配置解析
事务处理过程
基本概念
事务隔离级别
在同时进行多个事务的时候, 可能会出现脏读, 不可重复读, 幻读四种情况, 数据库分别有四种隔离级别处理这些情况. Spring 中 TransactionDefinition 定义了事务的隔离级别和传播属性, 隔离级别有
ISOLATION_DEFAULT:PlatforTransactionManager 默认的隔离级别, 也就是数据库默认的隔离级别, 下面四中分别对应数据库四中隔离级别
ISOLATION_READ_UNCOMMITED: 在另外一个事务未提交的时候可以读取另一个事务中的数据, 会出现脏读, 不可重复读, 幻读, 系统开销最小, 没有加锁
ISOLATION_READ_COMMITED: 在另外一个事务提交之后才可以读取数据, 防止了脏读, 会出现不可重复读, 幻读
ISOLATION_REPEATABLE_READ: 防止了脏读, 不可重复读 (在一个事物读取数据之后, 第一个事务提交数据, 第一个事务再次读取数据, 发现前后不一致), 会出现幻读, 读不加锁, 增删改加锁
ISOLATION_SERIALIZABLE: 可以防止脏读, 不可重复读, 幻读 (第一个事务修改涉及到了数据库中全部行, 第二个事务向表中插入一行, 第一个事务会发现表中还有没有修改的行)
spring 事务传播属性
传播属性: 定义了多层事务时候的行为, spring 的 TransactionDefinition 定义了 7 种事务传播行为
PROPAGETION_REQUIRED: 如果已经有事务, 则使用当前事务, 如果没有则新开一个事务
PROPAGETION_SUPPORT: 如果已经有事务则事务的执行, 如果没有则非事务地执行
PROPAGERION_MANDATORY: 如果有事务则支持事务, 否则抛出异常
PROPAGETION_REQUIRES_NEW: 总是开启一个新的事务, 如果已经有事务, 则挂起当前事务
PROPAGETION_NOT_SUPPORT: 总是非事务执行, 如果有事务则挂起
PROPAGETION_NEVER: 总是非事务执行, 如果有事务则抛出异常
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
解析该标签的时候做了以下的事
注册 org.springframework.aop.config.AopConfigUtils#AUTO_PROXY_CREATOR_BEAN_NAME,org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator
设置 InfrastructureAdvisorAutoProxyCreator 这个 bean 对应的属性, proxyTargetClass,exposeProxy
注册 bean:AnnotationTransactionAttributeSource
注册 bean:TransactionInterceptor
注册 bean:TransactionAttributeSourceAdvisor
注册组合 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 编程的时候使用事务的流程
拿到数据库连接
设置数据库连接为非自动提交
执行事务操作
提交事务
spring 事务处理的流程也基本相似, 只是做了一些封装
拿到数据库连接, 需要判断当前事务的传播级别, 有些传播级别需要新的数据库连接开启新的事务
设置数据库连接为非自动提交
执行事务操作
执行事务提交前的一些回调方法, 比如: beforeCommit
提交事务, 判断是否有异常, 是需要回滚还是提交
执行事务提交后的一个方法, 比如: afterCommit
总结
spring 事务在屏蔽了一些繁琐逻辑的同时, 也提供了比较好的扩展性, 比如支持自定义数据源, 自定义事务管理器, 而且支持在事务执行前后加入自己的回调用方法.
来源: https://www.cnblogs.com/sunshine-2015/p/10562202.html