【spring事务源码学习】--- spring事务三大接口简介


1 前言

spring为管理事务定义了三个接口,分别为

  • TransactionDefinition — 事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)
  • TransactionStatus — 事务的运行状态
  • PlatformTransactionManager — (平台)事务管理器

它们之间的关系大致为:PlatformTransactionManager根据TransactionDefinition 进行事务管理,管理过程中事务存在多种状态,每个状态信息通过 TransactionStatus 表示。本文将比较详细的介绍一下这三个接口。


2 TransactionDefinition接口

TransactionDefinition接口定义了5个方法以及一些表示事务属性的常量比如事务的隔离级别、传播行为等。其具体源码如下:

public interface TransactionDefinition {
	//-------------------------------------事务的七大传播行为---------------------------------------------
	/***如果当前没有事务,就新建一个事务,如果已经存在一个事务中,则加入到这个事务中*/
	int PROPAGATION_REQUIRED = 0;
	/***如果当前有事务,支持当前事务;如果当前没有事务,就以非事务方式执行*/
	int PROPAGATION_SUPPORTS = 1;
	/***使用当前事务,如果当前没有事务,就抛出异常*/
	int PROPAGATION_MANDATORY = 2;
	/***新建事务,如果当前存在事务,把当前事务挂起*/
	int PROPAGATION_REQUIRES_NEW = 3;
	/***以非事务方式执行操作,如果当前存在事务,就把当前事务挂起*/
	int PROPAGATION_NOT_SUPPORTED = 4;
	/***以非事务方式执行,如果当前存在事务,则抛出异常*/
	int PROPAGATION_NEVER = 5;
	/***如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作*/
	int PROPAGATION_NESTED = 6;

	//-------------------------------------事务的四大隔离级别---------------------------------------
	/***使用后端数据库默认的隔离级别,比如MySQL默认采用REPEATABLE_READ,Oracle默认采用READ_COMMITTED*/
	int ISOLATION_DEFAULT = -1;
	/***最低的隔离级别,允许读取尚未提交的数据变更,可能导致脏读、不可重复读和幻读*/
	int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
	/***允许读取开发事务已提交的数据,可以阻止脏读,但是不可重复读和幻读有可能发生*/
	int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
	/***对同一字段的多次读取结果都是一致的,除非数据是被本身事务所修改,
	可以防止脏读和不可重复读,但是幻读可能发生*/
	int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
	/***最高隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,
	该级别可以防止脏读、不可重复度和幻读,但是这将严重影响程序的性能,因此通常情况下根本不会用到该级别*/
	int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;
 
	 /**
	 * Use the default timeout of the underlying transaction system,
	 * or none if timeouts are not supported.
	 */
	int TIMEOUT_DEFAULT = -1;

	//-------------------------------------一些方法---------------------------------------
	/***获取事务的传播行为*/
	int getPropagationBehavior();
	/***获取事务的隔离级别*/
	int getIsolationLevel();
	/***获取事务的超时时间*/
	int getTimeout();
	/***返回当前事务是否为只读事务*/
	boolean isReadOnly();
	/***获取当前事务的名称*/
	@Nullable
	String getName();
}

3 PlatformTransactionManager接口

PlatformTransactionManager为事务管理器的顶级接口,其源码如下:

public interface PlatformTransactionManager {
	
	/***获取事务状态*/
	TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException;
	
	/***进行事务提交*/
	void commit(TransactionStatus status) throws TransactionException;

	/***进行事务回滚*/
	void rollback(TransactionStatus status) throws TransactionException;
}

提到事务管理器接口就不得不提设计模式中的模版模式。相信大家肯定都知道对于JDBC来说进行事务的开启、关闭与回滚其实都是对Connection对象的操作,而Hibernate则使用的是Session,两者的事务管理器肯定不可能是一个;同时不同的持久层框架,可能针对事务的管理也不尽相同。但是尽管如此,对于事务的管理,肯定还是可以抽象出很多相同的方法或属性,于是spring定义了一个顶级接口PlatformTransactionManager用来规定事务的基本操作,即获取事务状态、进行事务提交和进行事务回滚。同时还提供了一个抽象类AbstractPlatformTransactionManager用来定义一些关于事务管理的公共方法和属性。并且针对JTA和JDBC提供了相应事务管理器的具体实现 — JtaTransactionManager和DataSourceTransactionManager。继承和实现关系如下:
在这里插入图片描述


当然如果您的项目使用的是hibernate或spring-data-jpa作为持久层框架的话,spring也为此提供了事务管理器的具体实现,我们可以在pom.xml中导入spring-data-jpa(spring-data-jpa底层也用到了hibernate,因此导入spring-data-jpa的包可以同时获得jpa的事务管理器和hibernate的事务管理器)的包来验证一下:

  • jar包
 <!--jpa-->
 <dependency>
     <groupId>org.springframework.data</groupId>
     <artifactId>spring-data-jpa</artifactId>
     <version>2.2.0.RELEASE</version>
 </dependency>
  • 事务管理器的继承和实现关系:

在这里插入图片描述
通过上图可以看到 spring 确实是利用模版模式为各种持久层框架提供其适用的事务管理器。
如果仔细看一下这些事务管理器相关的接口、抽象类和实现类的作者,你会发现竟然都是一个人:

@author Juergen Hoeller

牛!!!


4 TransactionStatus接口

TransactionStatus接口用来记录事务的状态,该接口定义了一组方法,用来获取或判断事务的状态信息。

注意:PlatformTransactionManager接口中getTransaction(…)方法可能是获取一个在当前调用堆栈中已经存在的事务>状态对象 — TransactionStatus ,也可能能是新建一个事务,并获取到该事务的事务状态对象。

TransactionStatus接口源码如下:

public interface TransactionStatus extends SavepointManager, Flushable {

	/***当前事务是否为新事物*/
	boolean isNewTransaction();

	/***是否有保存点 --- 传播行为里NESTED就是用savepoint来实现的。*/
	boolean hasSavepoint();
	
	/***设置为只回滚 --- 传播行为是REQUIRED,内层子级报异常,父级肯定回滚就用到了rollback-only*/
	void setRollbackOnly();
	
	/***是否为只回滚*/
	boolean isRollbackOnly();

	/**
	 * Flush the underlying session to the datastore, if applicable:
	 * for example, all affected Hibernate/JPA sessions.
	 * <p>This is effectively just a hint and may be a no-op if the underlying
	 * transaction manager does not have a flush concept. A flush signal may
	 * get applied to the primary resource or to transaction synchronizations,
	 * depending on the underlying resource.
	 */
	@Override
	void flush();

	/***判断当前事务是否已经完成*/
	boolean isCompleted();
}
发布了189 篇原创文章 · 获赞 187 · 访问量 39万+

猜你喜欢

转载自blog.csdn.net/nrsc272420199/article/details/103645014