spring事务原理

198 阅读3分钟

这是我参与更文挑战的第5天,活动详情查看: 更文挑战

我们都知道spring的事务是由Aop实现的,spring会先生成代理对象,然后通过TransactionIntercept调用invoke方法来实现具体的逻辑。这个我们稍后再看

一、相关概念

我们先再复习一下老生常谈的事务的ACID特性

A:atomicity(原子性):操作不能被分割,要么全部成功,要么全部失败。 C:consistency(一致性):事务将数据从一个一致状态转移到另一个一致状态 I: isolation(隔离性):隔离性可以防止多个事务并发执行时由于交叉执行而导致的不一致。 D:durability(持久性):对数据的修改是永久的。

事务的隔离级别:

读未提交(Read Uncommit):可能产生脏读,即读到其他事务未提交的数据 读已提交(Read commit):可能不可重复读的问题,即两次读取结果不一致 可重复读(Repeatable read): 可能发生幻读,数据在update之后可以读到其他已提交事务的数据。(mvcc相关,后续会分享) 可串行化

二、spring事务的相关api

  1. 事务定义:包含事务的隔离级别和事务的传播行为等信息

image.png

  1. 事务属性:实现了回滚规则的扩展 TransactionAttribute extends TransactionDefinition

boolean rollbackOn(Throwable ex);

  1. 事务管理器:
public interface PlatformTransactionManager {

	TransactionStatus getTransaction(@Nullable TransactionDefinition definition)throws TransactionException;

	void commit(TransactionStatus status) throws TransactionException;

	void rollback(TransactionStatus status) throws TransactionException;

}
  1. 事务运行时状态:
public interface TransactionStatus extends SavepointManager, Flushable {

	boolean isNewTransaction();

	boolean hasSavepoint();//回滚到哪个点

	void setRollbackOnly();

	boolean isRollbackOnly();

	@Override
	void flush();

	boolean isCompleted();

}
  1. 事务拦截器:TransactionInterceptor

image.png

  1. 事务切面支持:TransactionAspectSupport 内部类TransactionInfo封装了事务的属性。
protected final class TransactionInfo {

		@Nullable
		private final PlatformTransactionManager transactionManager;

		@Nullable
		private final TransactionAttribute transactionAttribute;

		private final String joinpointIdentification;

		@Nullable
		private TransactionStatus transactionStatus;

		@Nullable
		private TransactionInfo oldTransactionInfo;

		public TransactionInfo(@Nullable PlatformTransactionManager transactionManager,
				@Nullable TransactionAttribute transactionAttribute, String joinpointIdentification) {

			this.transactionManager = transactionManager;
			this.transactionAttribute = transactionAttribute;
			this.joinpointIdentification = joinpointIdentification;
		}

		public PlatformTransactionManager getTransactionManager() {
			Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
			return this.transactionManager;
		}

		@Nullable
		public TransactionAttribute getTransactionAttribute() {
			return this.transactionAttribute;
		}

		/**
		 * Return a String representation of this joinpoint (usually a Method call)
		 * for use in logging.
		 */
		public String getJoinpointIdentification() {
			return this.joinpointIdentification;
		}

		public void newTransactionStatus(@Nullable TransactionStatus status) {
			this.transactionStatus = status;
		}

		@Nullable
		public TransactionStatus getTransactionStatus() {
			return this.transactionStatus;
		}

		/**
		 * Return whether a transaction was created by this aspect,
		 * or whether we just have a placeholder to keep ThreadLocal stack integrity.
		 */
		public boolean hasTransaction() {
			return (this.transactionStatus != null);
		}

		private void bindToThread() {
			// Expose current TransactionStatus, preserving any existing TransactionStatus
			// for restoration after this transaction is complete.
			this.oldTransactionInfo = transactionInfoHolder.get();
			transactionInfoHolder.set(this);
		}

		private void restoreThreadLocalStatus() {
			// Use stack to restore old transaction TransactionInfo.
			// Will be null if none was set.
			transactionInfoHolder.set(this.oldTransactionInfo);
		}

		@Override
		public String toString() {
			return (this.transactionAttribute != null ? this.transactionAttribute.toString() : "No transaction");
		}
	}

我们前文提到的事务拦截器TransactionInterceptor在invoke方法中,通过调用父类TransactionAspectSupport的invokeWithinTransaction方法进行事务处理,该方法支持声明式事务和编程式事务。

@Override
	@Nullable
	public Object invoke(MethodInvocation invocation) throws Throwable {
		// Work out the target class: may be {@code null}.
		// The TransactionAttributeSource should be passed the target class
		// as well as the method, which may be from an interface.
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

		// Adapt to TransactionAspectSupport's invokeWithinTransaction...
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,final InvocationCallback invocation) throws Throwable {
    //查询目标方法事务属性、确定事务管理器、构造连接点标识(用于确认事务名称)
    TransactionAttributeSource tas = getTransactionAttributeSource();
    final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
    final PlatformTransactionManager tm = determineTransactionManager(txAttr);
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

    // 事务获取
 TransactionInfotxInfo=createTransactionIfNecessary(tm,txAttr,joinpointIdentification);

    Object retVal;
    try {
             // 通过回调执行目标方法
            retVal = invocation.proceedWithInvocation();
    }
    catch (Throwable ex) {
            //目标方法执行抛出异常,根据异常类型执行事务提交或者回滚操作
            completeTransactionAfterThrowing(txInfo, ex);
            throw ex;
    }
    finally {
            //清理当前线程事务信息
            cleanupTransactionInfo(txInfo);
    }
    //目标方法执行成功,提交事务
    commitTransactionAfterReturning(txInfo);
    return retVal;
}

以上,感谢阅读。