Spring源码:事务

前言

首先,上一篇我大致分析了一下AOP的实现原理:Spring源码:AOP
我们都知道Spring的事务是基于AOP实现的,所以要明白事务的话首先要了解AOP的原理。

下面我们就看看一些事务的基础知识吧!

事务隔离级别

Spring事务隔离级别有五个,比数据库事务隔离级别多一个default。事务隔离级别定义TransactionDefinition中常量。

  1. default (默认)
    这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应。

  2. read_uncommitted (读未提交)
    这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。

  3. read_committed (读已提交)
    保证一个事务修改的数据提交后才能被另外一个事务读取,另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。

  4. repeatable_read (可重复读)
    这种事务隔离级别可以防止脏读、不可重复读,但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读。

  5. serializable(串行化)
    这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。除了防止脏读、不可重复读外,还避免了幻像读。

事务传播属性

在TransactionDefinition接口中定义了八个表示事务传播行为的常量。可以分为两种,一种支持当前事务,另一种不支持当前事务

支持当前事务的有:

  1. Required(默认属性)
    如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。
  2. Supports
    支持当前事务,如果当前没有事务,就以非事务方式执行。
  3. Mandatory
    支持当前事务,如果当前没有事务,就抛出异常。
  4. Nested
    支持当前事务,新增Savepoint点,与当前事务同步提交或回滚。
    嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。

不支持当前事务的有:

  1. requires_new
    新建事务,如果当前存在事务,把当前事务挂起。

  2. Never
    以非事务方式执行,如果当前存在事务,则抛出异常。

  3. Not_supports
    以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

知道这些基础知识,下面我们就开始源码分析

代理对象

首先,如果方法上添加了@Transactional注解,代理后的对象的拦截器链上增加了TransactionInterceptor这个链路,我们调用代理后对象的方法,就会执行这个类的invoke(),下面我们就看看这个TransactionInterceptor.invoke()
在这里插入图片描述

源码分析

  1. 首先TransactionInterceptor.invoke()会调用TransactionAspectSupport.invokeWithinTransaction()方法,Spring事务所有的逻辑都在这里。
  2. 这个方法里会做一些准备工作:先获取@Transactional注解的属性值,再获取事务管理器,这里我们能实现自己事务管理器,扩展用。最后会获取添加了@Transactional注解的方法。
  3. 最后会进行最核心的五步:开启事务(会创建数据库连接)、执行业务方法、异常回滚逻辑、事务传播(处理挂起的事务)、提交事务
// 1. 核心逻辑:开启事务
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
try {
	// 2. 执行@Transactional注解的方法:业务逻辑方法
	retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
	// 3. 出现异常,进行回滚:并抛出异常
	completeTransactionAfterThrowing(txInfo, ex);
	throw ex;
}
finally {
	// 4. 事务传播,处理挂起的事务
	cleanupTransactionInfo(txInfo);
}
// 5. commit 提交事务
commitTransactionAfterReturning(txInfo);
  1. 开启事务:开启事务的时候会先从线程的ThreadLocal中获取,如果获取不到会创建一个事务,如果获取到会根据传播属性,来确定是否要新开启一个事务(也就是重新创建一个数据库连接)和是否需要把当前事务挂起,创建一个事务的时候有一个非常重要的属性newTrasaction = true,后面提交事务的时候会根据这个属性来判断嵌套事务的提交时机。(比如:REQUIRES_NEW就会挂起外层事务,创建一个新事务;NESTED会创建一个sava point回滚点,还会把外层事务的newTrasaction属性设置为false,也就是内层事务不提交。)
  2. 执行业务逻辑就不说了。
  3. 异常回滚逻辑:如果执行中出现异常,会先判断异常类型是否是需要回滚的类型,是就调用rollback回滚,不是回滚类型就提交事务,并且向外层抛出异常。
  4. 处理事务:这一步就是把ThreadLocal中的值set成老事务。
  5. 提交事务:这进行判断最后这个事务到底是回滚还是提交,如果回滚 是不是有回滚点,有回滚点就使用回滚点回滚,如果提交,会判断是否有回滚点,有就释放回滚点,还会判断newTrasaction == true ?是的话就提交。嵌套事务,requires_new传播属性newTrasaction就是true,nested传播属性newTrasaction就是false,但是有回滚点,会释放回滚点。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值