0
点赞
收藏
分享

微信扫一扫

Spring AOP事务实现原理之事务拦截器TransactionInterceptor

small_Sun 2022-03-16 阅读 69

学习这篇博文需要首先明白Spring AOP的实现原理,可以参考Spring的BeanPostProcessor扩展点实现类AbstractAutoProxyCreator和Spring AOP创建代理类之JdkDynamicAopProxy这两篇博文。

TransactionInterceptor

该类是Advice实现类,用于对事务性的方法进行拦截,使用通用 Spring的事务基础类
(PlatformTransactionManager/ReactiveTransactionManager)进行声明式事务管理。

  • 派生自 {@link TransactionAspectSupport} 类,该类包含与 Spring 的底层事务 API 的集成。

  • TransactionInterceptor 只是以正确的顺序调用相关的超类方法,例如 {@link #invokeWithinTransaction}

  • TransactionInterceptors是线程安全的

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

	public TransactionInterceptor() {}

	/**
	 * 创建一个新的事务拦截器TransactionInterceptor.
	 * @param ptm 默认的事务管理器,通过该事务管理器进行实际的事务管理
	 * @param attributes properties形式的事务属性
	 */
	public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) {
		setTransactionManager(ptm);
		setTransactionAttributes(attributes);
	}

	/**
	 * 创建一个新的事务拦截器TransactionInterceptor
	 * @param ptm 默认的事务管理器,通过该事务管理器进行实际的事务管理
	 * @param tas 事务属性源TransactionAttributeSource
	 */
	public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) {
		setTransactionManager(ptm);
		setTransactionAttributeSource(tas);
	}

	@Override
	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);

		//适配到父类TransactionAspectSupport的invokeWithinTransaction方法
        //第三个参数是InvocationCallback接口,可以保证在父类TransactionAspectSupport#invokeWithinTransaction方法中回调到当前方法的拦截器链条
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}
}

TransactionAspectSupport

事务aspect的基类,例如 {@link TransactionInterceptor}AspectJ aspect。

  • 通过策略模式,使用{@link PlatformTransactionManager}{@link ReactiveTransactionManager}的实现类执行实际的事务管理工作,一个{@link TransactionAttributeSource}用于一个确定的类或方法的事务定义。
  • 如果在 {@link TransactionAttribute} 中没有指定事务名称,则默认名称将是 {@code 完全限定的类名 + "." + 方法名}
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
    //事务信息持有者,支持{@code currentTransactionStatus()}方法,并支持互相协作的不同advice之间的通信(例如,@Before 和@After)
	private static final ThreadLocal<TransactionInfo> transactionInfoHolder =
			new NamedThreadLocal<>("Current aspect-driven transaction");
    
     //事务管理器名称
    @Nullable
	private String transactionManagerBeanName;
    //事务管理器
	@Nullable
	private TransactionManager transactionManager;
    //事务属性源
	@Nullable
	private TransactionAttributeSource transactionAttributeSource;
    //Bean工厂
	@Nullable
	private BeanFactory beanFactory;
	
	
    //TransactionAspectSupport内部接口用于继续进行目标方法调用的简单回调接口
	@FunctionalInterface
	protected interface InvocationCallback {
		Object proceedWithInvocation() throws Throwable;
	}
	
	//省略其他代码

currentTransactionInfo

用于返回当前事务信息 TransactionInfo

  • 如果实现的子类,不能在一个方法中处理所有的操作,例如一个AspectJ 切面涉及不同的@Before,@After通知,才需要使用这种机制来获取当前的 TransactionInfo。
  • 一个@Around通知可以在整个aspect方法中保存对 TransactionInfo 的引用。
  • 一个TransactionInfo始终会被返回,即使没有事务被创建,可以通过TransactionInfo.hasTransaction()方法查询是否有事务
	protected static TransactionInfo currentTransactionInfo() throws NoTransactionException {
		return transactionInfoHolder.get();
	}

currentTransactionStatus

返回当前方法调用中的事务状态 transaction status,主要用于设置当前事务rollback-only属性

	public static TransactionStatus currentTransactionStatus() throws NoTransactionException {
		TransactionInfo info = currentTransactionInfo();
		if (info == null || info.transactionStatus == null) {
			throw new NoTransactionException("No transaction aspect-managed TransactionStatus in scope");
		}
		return info.transactionStatus;
	}

TransactionInfo

TransactionAspectSupport静态内部类,表示事务信息

protected static final class TransactionInfo {

		//事务管理器
		private final PlatformTransactionManager transactionManager;

		//事务属性
		private final TransactionAttribute transactionAttribute;

        //字符串形式的连接点识别符,也就是事务所作用的方法,如com.aoptx.AServiceImpl.methodA
		private final String joinpointIdentification;

		//事务状态信息
		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;
		}

		public String getJoinpointIdentification() {
			return this.joinpointIdentification;
		}

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

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

        //返回该aspect是否创建了一个事务
		public boolean hasTransaction() {
			return (this.transactionStatus != null);
		}

        //将该事务信息绑定到当前线程
		private void bindToThread() {
            //暴露当前事务状态TransactionStatus,保存任何已经存在的事务状态,以便在此事务完成后进行恢复
			this.oldTransactionInfo = transactionInfoHolder.get();
			transactionInfoHolder.set(this);
		}

        //恢复之前已经存在的事务信息
		private void restoreThreadLocalStatus() {
			transactionInfoHolder.set(this.oldTransactionInfo);
		}
	}

invokeWithinTransaction

	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {

        //获取事务属性源TransactionAttributeSource
		TransactionAttributeSource tas = getTransactionAttributeSource();
        //获取当前调用的方法的事务属性,如果TransactionAttribute为null,则该方法就是非事务方法
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
        
        //通过TransactionAttribute获取事务管理器TransactionManager
		final TransactionManager tm = determineTransactionManager(txAttr);

        //1.ReactiveTransactionManager类型的事务管理器,这个不常用,代码忽略
		
        //2.常用的PlatformTransactionManager事务管理器
		PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
        
        //连接点识别符,也就是事务所作用的方法,如com.aoptx.AServiceImpl.methodA
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
		if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
            
            //创建一个标准的事务,有getTransaction,commit,rollback
			TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

			Object retVal;
			try {
                //调用拦截器链条中的下一个拦截器,最终目标方法会被调用
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
                // 调用出现异常,进行处理
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
                //清除事务信息
				cleanupTransactionInfo(txInfo);
			}

			if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
				// Set rollback-only in case of Vavr failure matching our rollback rules...
				TransactionStatus status = txInfo.getTransactionStatus();
				if (status != null && txAttr != null) {
					retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
				}
			}
            //提交事务commit
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}

        //3.CallbackPreferringPlatformTransactionManager类型的事务管理器,不常用,代码忽略
		else {
		}
	}

createTransactionIfNecessary

	protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {

		// If no name specified, apply method identification as transaction name.
		if (txAttr != null && txAttr.getName() == null) {
			txAttr = new DelegatingTransactionAttribute(txAttr) {
				@Override
				public String getName() {
					return joinpointIdentification;
				}
			};
		}

        //从TransactionManager中获取事务,返回TransactionStatus
		TransactionStatus status = null;
		if (txAttr != null) {
			if (tm != null) {
                //调用抽象父类AbstractPlatformTransactionManger的getTransaction方法
				status = tm.getTransaction(txAttr);
			}
		}
		return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
	}

prepareTransactionInfo

为给定的属性TransactionAttribute和状态TransactionStatus准备一个 TransactionInfo。

	protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, String joinpointIdentification,
			@Nullable TransactionStatus status) {
	
        //只要进入到事务方法里,就会创建一个TransactionInfo
		TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
        //
		if (txAttr != null) {
			txInfo.newTransactionStatus(status);
		}
        //如果没有事务属性,则不需要创建事务
		else {
			// The TransactionInfo.hasTransaction() method will return false. We created it only
			// to preserve the integrity of the ThreadLocal stack maintained in this class.
			if (logger.isTraceEnabled()) {
				logger.trace("No need to create transaction for [" + joinpointIdentification +
						"]: This method is not transactional.");
			}
		}
        //将TransactionInfo绑定到当前线程,即使我们在这里没有创建一个新的事务
        //这保证了TransactionInfo堆栈将被正确管理,即使这个aspect没有创建任何事务。
		txInfo.bindToThread();
		return txInfo;
	}

completeTransactionAfterThrowing

	protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
		if (txInfo != null && txInfo.getTransactionStatus() != null) {
            
            //如果事务属性不为空,且事务对该异常ex进行回滚,则调用事务管理器进行事务回滚
            //可以通过Transactional注解中rollbackFor、rollbackForClassName、noRollbackFor、noRollbackForClassName配置
			if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
                //调用事务管理器进行事务的回滚
				try {
					txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
				}
				catch (TransactionSystemException ex2) {
					ex2.initApplicationException(ex);
					throw ex2;
				}
				catch (RuntimeException | Error ex2) {
					throw ex2;
				}
			}
	        //如果异常不满足,则进行提交commit,但是如果TransactionStatus.isRollbackOnly()方法被设置为true,那么仍然会回滚
			else {
				// We don't roll back on this exception.
				// Will still roll back if TransactionStatus.isRollbackOnly() is true.
				try {
					txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
				}
				catch (TransactionSystemException ex2) {
					ex2.initApplicationException(ex);
					throw ex2;
				}
				catch (RuntimeException | Error ex2) {
					throw ex2;
				}
			}
		}
	}

commitTransactionAfterReturning

执行事务提交,如果没有事务,则什么也不做

	protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
		//如果事务信息不为null,则进行事务提交
        if (txInfo != null && txInfo.getTransactionStatus() != null) {
            //委托给具体的TransactionManager进行事务提交
			txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
		}
	}

扩展学习

  • Spring 的注解方式的事务实现机制
  • Spring的BeanPostProcessor扩展点实现类AbstractAutoProxyCreator
  • Spring AOP创建代理类之JdkDynamicAopProxy
  • Spring 的注解方式的事务实现机制
  • Spring的TransactionDefinition中定义的事务的传播特性和隔离级别
  • [详解Spring的事务管理PlatformTransactionManager](
举报

相关推荐

0 条评论