Spring事务源码阅读(一)

Spring事务

注解一:@EnableTransactionManagement

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

	/** 是否使用cglib代理 默认是jdk代理 这个参数 也会影响 EnableAspectJAutoProxy注解生成代理对象的方式
	 */
	boolean proxyTargetClass() default false;

	/**
	 * 表明会使用哪种代理方式 aspectj 或者spring AOP
	 */
	AdviceMode mode() default AdviceMode.PROXY;

	/** 通知的优先级 
	 */
	int order() default Ordered.LOWEST_PRECEDENCE;

}

这个注解 导入了TransactionManagementConfigurationSelector类

TransactionManagementConfigurationSelector

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

	/**
	 * 导入了两个配置类AutoProxyRegistrar ProxyTransactionManagementConfiguration
	 */
	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
				return new String[] {AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {determineTransactionAspectClass()};
			default:
				return null;
		}
	}

	private String determineTransactionAspectClass() {
		return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
				TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
				TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
	}

}

selectImports 方法,默认是adviceMode 是 PROXY,导入了AutoProxyRegistrarProxyTransactionManagementConfiguration,第一个类用于开启代理,

这个类是 主要用于 将 @EnableTransactionManagement 注解上的信息进行解析后,再往容器中注册一个BeanDefinition,这个BeanDefinition被用于代理类的创建,BeanDefinition内的类型是InfrastructureAdvisorAutoProxyCreatorInfrastructureAdvisorAutoProxyCreator实现了BeanPostProcess

注: @EnableTransactionManagement@EnableAspectJAutoProxy 都是调用这个方法 ,由于传入参数的类型不同,但是注入的BeanDefinition中的名称会一样的,获取会导致类的覆盖,@EnableTransactionManagement传入的是InfrastructureAdvisorAutoProxyCreator ,而@EnableAspectJAutoProxy 传入的是AnnotationAwareAspectJAutoProxyCreator,两个类的优先级比较的话,AnnotationAwareAspectJAutoProxyCreator更高,具体代码在AopConfigUtils#registerOrEscalateApcAsRequired.

ProxyTransactionManagementConfiguration

这是一个配置类,用于注册事务管理器组件,一共注册三个组件,

  • BeanFactoryTransactionAttributeSourceAdvisor: 事务增强器,其中有两个属性,一个是标签解析器(PointCut),还有一个拦截器
  • TransactionAttributeSource: 用于解析@Transacational注解
  • TransactionInterceptor: 方法拦截器,这个类继承了MethodInterceptor,那么其中的核心方法就是invoke方法,

TransactionInterceptor#invoke

@Override
	@Nullable
	public Object invoke(MethodInvocation invocation) throws Throwable {
		
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
		// Adapt to TransactionAspectSupport's invokeWithinTransaction... 核心方法
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}

invoke内部调用的invokeWithinTransaction

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

   //得到 TransactionAttributeSource 这个是之前注册进去的,
   //1.获得事务属性
   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);

   if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
      //2.创建事务
      TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

      Object retVal;
      try {
         //3。执行业务逻辑
         retVal = invocation.proceedWithInvocation();
      }
      catch (Throwable ex) {
         // target invocation exception 4。出现异常 在异常情况下完成事务
         completeTransactionAfterThrowing(txInfo, ex);
         throw ex;
      }
      finally {
         //5。清除事务信息
         cleanupTransactionInfo(txInfo);
      }
      //6。提交事务
      commitTransactionAfterReturning(txInfo);
      return retVal;
   }

   else {
      final ThrowableHolder throwableHolder = new ThrowableHolder();
      // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
      try {
         Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
            TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
            try {
               return invocation.proceedWithInvocation();
            }
            catch (Throwable ex) {
               if (txAttr.rollbackOn(ex)) {
                  // A RuntimeException: will lead to a rollback.
                  if (ex instanceof RuntimeException) {
                     throw (RuntimeException) ex;
                  }
                  else {
                     throw new ThrowableHolderException(ex);
                  }
               }
               else {
                  // A normal return value: will lead to a commit.
                  throwableHolder.throwable = ex;
                  return null;
               }
            }
            finally {
               cleanupTransactionInfo(txInfo);
            }
         });

         // Check result state: It might indicate a Throwable to rethrow.
         if (throwableHolder.throwable != null) {
            throw throwableHolder.throwable;
         }
         return result;
      }
      catch (ThrowableHolderException ex) {
         throw ex.getCause();
      }
      catch (TransactionSystemException ex2) {
         if (throwableHolder.throwable != null) {
            logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
            ex2.initApplicationException(throwableHolder.throwable);
         }
         throw ex2;
      }
      catch (Throwable ex2) {
         if (throwableHolder.throwable != null) {
            logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
         }
         throw ex2;
      }
   }
}

代码分成了两块

  • 标准式事务管理
  • 回调来完成事务管理

标准的事务管理分为6个步骤

  1. 获取事务属性
  2. 创建事务
  3. 执行业务逻辑
  4. 异常情况下完成事务
  5. 清除事务信息
  6. 提交事务

获取事务属性

通过getTransactionAttribute 方法来解析注解,获取属性,会优先从缓存中找,找不到的进行构建

@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
   if (method.getDeclaringClass() == Object.class) {
      return null;
   }
   //从缓存中找
   Object cacheKey = getCacheKey(method, targetClass);
   TransactionAttribute cached = this.attributeCache.get(cacheKey);
   if (cached != null) {
      if (cached == NULL_TRANSACTION_ATTRIBUTE) {
         return null;
      }
      else {
         return cached;
      }
   }
   else {
      // We need to work it out.缓存中没有去执行 得到后放入到缓存中
      TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
      // Put it in the cache.
      //如果结果为null 也放入到缓存中 进行一个标志 表示不需要事务进行管理
      if (txAttr == null) {
         this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
      }
      else {
         String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
         if (txAttr instanceof DefaultTransactionAttribute) {
            ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
         }
         if (logger.isTraceEnabled()) {
            logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
         }
         this.attributeCache.put(cacheKey, txAttr);
      }
      return txAttr;
   }
}
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
   // Don't allow no-public methods as required. 放在非public上不生效
   if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
      return null;
   }

   // The method may be on an interface, but we need attributes from the target class.
   // If the target class is null, the method will be unchanged.
   //method 可能是接口的方法,specificMethod是实际的方法
   Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

   // First try is the method in the target class.
   //先从目标方法上中找
   TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
   if (txAttr != null) {
      return txAttr;
   }

   // Second try is the transaction attribute on the target class.
   //在当前类上去找
   txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
   if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
      return txAttr;
   }
   //降级到接口 与接口方法中找
   if (specificMethod != method) {
      // Fallback is to look at the original method.
      txAttr = findTransactionAttribute(method);
      if (txAttr != null) {
         return txAttr;
      }
      // Last fallback is the class of the original method.
      txAttr = findTransactionAttribute(method.getDeclaringClass());
      if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
         return txAttr;
      }
   }

   return null;
}

注意:

computeTransactionAttribute 方法中 第一个if判断,对于方法的作用范围有一个判断,非public修饰的方法不会生效

computeTransactionAttribute获取注解信息,是一个逐渐降级的过程,从一开始的在对应方法上找,再到当前类上找,最后再到方法实现的接口上找

在解析完成后,当解析的结果是一个null 也会被放入缓存中,

创建事务

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;
         }
      };
   }

   TransactionStatus status = null;
   if (txAttr != null) {
      if (tm != null) {
         //调用事务管理器的方法 获取一个事务并返回状态
         status = tm.getTransaction(txAttr);
      }
      else {
         if (logger.isDebugEnabled()) {
            logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
                  "] because no transaction manager has been configured");
         }
      }
   }
   //封装到 TransactionInfo对象中 并将TransactionInfo绑定到当前线程
   return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

创建事务 就是创建了一个TransactionInfo,其中包含了事务管理器,事务属性,事务状态,上一个事务的信息(只在嵌套事务中被用到)

核心方法就是

  • getTransaction
  • prepareTransactionInfo

这是spring事务中最麻烦的,涉及到了事务的传播行为

事务的传播行为

Alt

@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
   //得到一个数据库事务对象封装了一个从当前线程中获取到的连接 一开始 是返回一个没有数据库连接的DataSourceTransactionObject
   Object transaction = doGetTransaction();

   // Cache debug flag to avoid repeated checks.
   boolean debugEnabled = logger.isDebugEnabled();

   if (definition == null) {
      // Use defaults if no transaction definition given.
      definition = new DefaultTransactionDefinition();
   }
   //是否存在事务 只有 required_new 的情况 会开启一个线程 有些是直接加入了外部的事务 比如 supports、required、mandatory
   // 而nested 不仅计入了外部事务 还设置了一个保存点 如果事务发生了异常 只有回滚到保存点 由于直接复用外部事务 嵌套事务 随着外部事务的回滚而回滚
   if (isExistingTransaction(transaction)) {
      //检查传播类型进行不同处理 这里进去是对嵌套事务的梳理
      // Existing transaction found -> check propagation behavior to find out how to behave.
      return handleExistingTransaction(definition, transaction, debugEnabled);
   }

   // Check definition settings for new transaction.
   //超时检验 默认-1 不进行校验
   if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
      throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
   }

   // No existing transaction found -> check propagation behavior to find out how to proceed.
   // mandatory 没有事务存在 抛出异常
   if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
      throw new IllegalTransactionStateException(
            "No existing transaction found for transaction marked with propagation 'mandatory'");
   }
   else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
         definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
         definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
      //创建新事务
      //如果存在同步 就把注册的同步挂起 传入null的话 就返回null
      SuspendedResourcesHolder suspendedResources = suspend(null);
      if (debugEnabled) {
         logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
      }
      try {
         boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
         //根据之前事务定义的信息 构造一个事务状态对象
         DefaultTransactionStatus status = newTransactionStatus(
               definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
         //开启一个新事务 并将数据库连接 绑定要线程上
         doBegin(transaction, definition);
         //激活同步
         prepareSynchronization(status, definition);
         return status;
      }
      catch (RuntimeException | Error ex) {
         resume(null, suspendedResources);
         throw ex;
      }
   }
   else {
      // Create "empty" transaction: no actual transaction, but potentially synchronization.
      if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
         logger.warn("Custom isolation level specified but no actual transaction initiated; " +
               "isolation level will effectively be ignored: " + definition);
      }
      //创建一个空事务 没有回滚设置 与事务提交
      boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
      //绑定要当前线程上
      return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
   }
}

这段代码 被分成了两种情况来考虑

一种是直接调用事务

还是一种是事务内的嵌套事务

Alt

在代码中 可以发现在嵌套事务的情况下,只有传播级别为required_new的情况才会去调用startTransaction方法,也就是开启一个新事务,其他情况都是复用外围的事务,

我们看一段代码 位于 AbstractTransactionStatus# handleExistingTransaction,是嵌套事务中对于 NOT_SUPPORTED类型的事务的处理,基本上对于代码已经注释了,

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
   if (debugEnabled) {
      logger.debug("Suspending current transaction");
   }
   //挂起 挂起是指 清空外部事务绑定在线程的同步
   // 挂起后 将来还要恢复的 要将清除的信息 保存到当前的事务上,当当前事务完成后,保证外围事务也能运行
   // suspendedResources 标示挂起的资源
   Object suspendedResources = suspend(transaction);
   boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
   //创建一个新事务 标示不存在一个真正的事务 不需要进行回滚
   return prepareTransactionStatus(
         definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}

这里完成了一个是对于外部事务的挂起,挂起分成两个动作

  • 清空外部事务在线程上的同步
  • 挂起后为了后续线程的恢复,要将信息保存下来,方便后续将事务进行恢复

这里调用的是 prepareTransactionStatus方法,而不是startTransaction两者的区别就是 后者会从数据库中获取链接,而前者不会获取链接,在PROPAGATION_REQUIRES_NEW 传播类型下 就是直接使用startTransaction`。

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
   if (debugEnabled) {
      logger.debug("Suspending current transaction, creating new transaction with name [" +
            definition.getName() + "]");
   }
   SuspendedResourcesHolder suspendedResources = suspend(transaction);
   try {
      boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
      //这里将 旧事务的信息 也加进去了 有自己的提交跟回滚机制
      DefaultTransactionStatus status = newTransactionStatus(
            definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
      doBegin(transaction, definition);
      prepareSynchronization(status, definition);
      return status;
   }
   catch (RuntimeException | Error beginEx) {
      resumeAfterBeginException(transaction, suspendedResources, beginEx);
      throw beginEx;
   }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值