当前位置:   article > 正文

Spring源码解析之-- 事务TransactionInterceptor 分析(开启事务)_transactiontimeinterceptor

transactiontimeinterceptor

一、介绍

Spring 事务分为两种,声明式和编程式, 声明式就是 在 方法或者接口上加 @Transactional的注解, 这样就可以交给Spring 管理它的提交,回滚,等等, 编程式就是用spring提供的模板 ,通过回调方法实现. 不管使用哪一种,最后事务的执行入口都是TransactionInterceptor的invoke方法,这个在上一章Spring源码解析之-- 事务注解 处理流程 分析中有介绍的. 下面就从这个入口,开始分析如何开启事务

二、TransactionInterceptor 分析

2. 流程

如下图,首先看一下事务的大致流程如下:
在这里插入图片描述
接下来再分析源码

2.1 invoke

invoke 方法就是一个入口, 主要就t是先获取对应的 targetClass, 然后适配类 TransactionAspectSupport 的invokeWithinTransaction 方法

	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.
		/**
		首先这里是需要获取 targetClass, 如果是代理类(如 CglibProxy或者 jdkProyx),那就 获取对应的 target class
		**/
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
		
		/**适配 类 TransactionAspectSupport 的invokeWithinTransaction 方法
		这里是传入了一个回调函数,也就是具体的处理逻辑
		**/
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

2.1.1 TransactionAspectSupport#invokeWithinTransaction

invokeWithinTransaction 这里主要做了以下几件事情:

  1. 获取事务的属性
  2. 加载配置中配的transactionManager
  3. 不同的事务处理方式使用不同的事务
  4. 在目标方法执行前获取事务并收集事务信息
  5. 执行目标方法
  6. 一旦出现异常,尝试异常处理,不是所有的异常都回滚, Spring 只对RuntimeException 处理
  7. 提交事务前的事务信息清除
  8. 提交事务
  protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {
			
		// 获取事务属性,如果 transaction attribute 为null, 那这个方法就是 非事务类型
		TransactionAttributeSource tas = getTransactionAttributeSource();
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		// 根据事务属性确定对应的事务
		final TransactionManager tm = determineTransactionManager(txAttr);
        // 这里是反应式事务,暂时不分析
		if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
			ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
				if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {
					throw new TransactionUsageException(
							"Unsupported annotated transaction on suspending function detected: " + method +
							". Use TransactionalOperator.transactional extensions instead.");
				}
				ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
				if (adapter == null) {
					throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
							method.getReturnType());
				}
				return new ReactiveTransactionSupport(adapter);
			});
			return txSupport.invokeWithinTransaction(
					method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
		}
        
		PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
		// 获取方法唯一标识,这里的 descriptor 就是在 获取 事务属性txAttr时 设置进去的.
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
        /**
        这里是 申明式事务
        我们一般申明式 事务定义的是DataSourceTransactionManager
         就不是CallbackPreferringPlatformTransactionManager,CallbackPreferringPlatformTransactionManager 是通过回调方法
         实现事务的
        **/
		if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
			// 创建 TransactionInfo 
			TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

			Object retVal;
			try {
				// This is an around advice: Invoke the next interceptor in the chain.
				// This will normally result in a target object being invoked.
				// 执行被争强方法
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// target invocation exception
				// 异常回滚
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
			     // 清除信息
				cleanupTransactionInfo(txInfo);
			}

			if (retVal != null && 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);
				}
			}
           // 提交
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}
       // 编程式事务
		else {
			Object result;
			final ThrowableHolder throwableHolder = new ThrowableHolder();

			// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
			try {
				result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
					TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
					try {
						Object retVal = invocation.proceedWithInvocation();
						if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
							// Set rollback-only in case of Vavr failure matching our rollback rules...
							retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
						}
						return retVal;
					}
					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);
					}
				});
			}
			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;
			}

			// Check result state: It might indicate a Throwable to rethrow.
			if (throwableHolder.throwable != null) {
				throw throwableHolder.throwable;
			}
			return result;
		}
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131

2.2 getTransactionAttribute

getTransactionAttribute 方法比较简单,就是获取事务属性并缓存, 如果事务存在,那就对事务 加一个属性描述,对应的值为 类名.方法名

public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
		// 如果是Object.class 类,直接返回
		if (method.getDeclaringClass() == Object.class) {
			return null;
		}

		/** 
		首先 去查看是否有缓存,getCacheKey 里面 就是一个单纯的 new 了一个对象 MethodClassKey,MethodClassKey重写了
		toString() 方法, 主要就是 用了 method+targetClass
		**/
		Object cacheKey = getCacheKey(method, targetClass);
		TransactionAttribute cached = this.attributeCache.get(cacheKey);
		// 如果不为null, 要么就是具体的事务属性,要么就是 默认的空属性, 如果是默认的空事务属性,那就 返回null
		if (cached != null) {
			if (cached == NULL_TRANSACTION_ATTRIBUTE) {
				return null;
			}
			else {
				return cached;
			}
		}
		else {
			// 如果是空 ,那就再次获取一遍
			TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
			// 放入缓存, 如果 属性为null, 设置 对应的value 为NULL_TRANSACTION_ATTRIBUTE
			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;
		}
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

2.3 computeTransactionAttribute

computeTransactionAttribute 方法主要是 寻找事务属性的, 主要流程如下:

  1. 首先判断 方法 是 什么类型的,如果不是 public 类型的,直接返回null
  2. 接下来获取 事务属性,这里是按照 targetClass.Method ->tragetClass ->interface.Method -> interface 的顺序获取属性的, 也就是说,如果 你 接口上有事务属性, 但是如果你目标类的 方法上还有属性,那就以 目标类的方法的属性为准
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
		/** 这里要求 事务的方法是 public的,不然不生效
           注解式事务里面 AnnotationTransactionAttributeSource 里面默认是 true 的
          **/
		if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
			return null;
		}

		/**
		 这里的方法可能是在一个接口上,所以这里是获取target class 的具体方法
		 比如: method 为IFoo.bar() , targetClass 是 DefaultFoo ,这里是需要获取 DefaultFoo.bar()方法
		 同时这里还处理了可能出现桥接的问题
		 如果 targetClass 为null ,那方法就不会变
		**/
		Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

		/**
		第一次尝试: 先对 方法上 @Transactional 进行解析
		 解析 方法上的@Transactional属性,利用 springTransactionAnnotationParser 对 方法上的
		 @Transactional 进行解析里面的属性, 返回 TransactionAttribute 
		**/
		TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
		if (txAttr != null) {
			return txAttr;
		}

		/**
		第二次: 如果上一步没有获取到,那就可能在 target class上面
		对 target class 进行解析, 如果找到对应的事务属性, 并且是 
		用户级别的方法,那就返回
		**/
		txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
		if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
			return txAttr;
		}

        /**
         第三步 如果 在目标类上的 方法和类上都没有找到 对应的 事务属性
         那就去 原始的接口上去寻找, 还是 先从 method 上面开始,
         如果没有,那就看接口上有没有 配置事务属性
        **/
		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;
			}
		}
         // 最后都没有找到,那就返回null
		return null;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

2.4 TransactionAspectSupport#determineTransactionManager

determineTransactionManager 方法的逻辑也比较简单:

  1. 判断是否有事务属性,如果没有直接返回
  2. 根据事务的名字,获取对应的事务管理器
  3. 如果事务没有设置名字, 获取默认的事务管理器
protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
		// 如果 事务属性 txAttr 为null, 那就直接返回
		if (txAttr == null || this.beanFactory == null) {
			return getTransactionManager();
		}
        // 获取对应的事务注解上的名字
		String qualifier = txAttr.getQualifier();
		if (StringUtils.hasText(qualifier)) {
		    // 根据指定的事务注解name去查询
			return determineQualifiedTransactionManager(this.beanFactory, qualifier);
		}
		//根据默认的事务注解name查询
		else if (StringUtils.hasText(this.transactionManagerBeanName)) {
			return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
		}
		else {
		    // 获取默认的 事务管理器
			TransactionManager defaultTransactionManager = getTransactionManager();
			if (defaultTransactionManager == null) {
				defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
				if (defaultTransactionManager == null) {
					defaultTransactionManager = this.beanFactory.getBean(TransactionManager.class);
					this.transactionManagerCache.putIfAbsent(
							DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
				}
			}
			return defaultTransactionManager;
		}
	}

    /**
     这里从(cache->beanFactory)里面获取 指定名字的事务管理器
    **/
	private TransactionManager determineQualifiedTransactionManager(BeanFactory beanFactory, String qualifier) {
	   // 这里首先也是先从缓存里面获取
		TransactionManager txManager = this.transactionManagerCache.get(qualifier);
		//如果缓存不存在,那就从BeanFactory 里面获取,然后再放进缓存
		if (txManager == null) {
			txManager = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
					beanFactory, TransactionManager.class, qualifier);
			this.transactionManagerCache.putIfAbsent(qualifier, txManager);
		}
		return txManager;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

2.5 TransactionAspectSupport#createTransactionIfNecessary

createTransactionIfNecessary 这个方法主要是判断是否有必要创建事务 ,

	protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
		/**
		如果没有指定名称,则将方法标识应用为事务名称,就是之前设置的 class.method
		**/
		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");
				}
			}
		}
		return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

2.6 AbstractPlatformTransactionManager#getTransaction

getTransaction方法 比较核心了, 主要做了以下几件事:
1.获取事务
2. 如果当前线程存在事务,则转向嵌套事务处理
3. 事务的超时设置验证
4. 事务的传播属性验证
5. 隔离级别, timeout ,connectinHolder 等配置
6. 绑定到当前线程

public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException {

		// 如果传入的definition 为null , 就从新定义一个新的definition (StaticTransactionDefinition 类型)
		TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
        //这里时获取 当前线程缓存在 threadlocal里面的 connection, 如果没有connection,那DataSourceTransactionObject 里面的
        //connectionHolder 为null
		Object transaction = doGetTransaction();
		boolean debugEnabled = logger.isDebugEnabled();
        // 这里时判断如果上面的 connectionHolder 不为空,并且是有效的
		if (isExistingTransaction(transaction)) {
			// Existing transaction found -> check propagation behavior to find out how to behave.
			// 这里是 为已经存在的 transaction创建一个 TransactionStatus对象
			return handleExistingTransaction(def, transaction, debugEnabled);
		}

		// Check definition settings for new transaction.
		if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
		}

		//如果事务定义为MANDATORY,那就是必须在一个已有事务里面运行, 这里没有事务就会报错
		if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
				// 这块空挂起,不做任何操作
			SuspendedResourcesHolder suspendedResources = suspend(null);
			if (debugEnabled) {
				logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
			}
			try {
			   // 这里就是开启事务
				return startTransaction(def, transaction, debugEnabled, suspendedResources);
			}
			catch (RuntimeException | Error ex) {
				resume(null, suspendedResources);
				throw ex;
			}
		}
		else {
			// Create "empty" transaction: no actual transaction, but potentially synchronization.
			if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
				logger.warn("Custom isolation level specified but no actual transaction initiated; " +
						"isolation level will effectively be ignored: " + def);
			}
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
		}
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

2.7 DataSourceTransactionManager#doGetTransaction

doGetTransaction 方法主要就是为了获取当前线程的 connection, 通过查看缓存在 TransactionSynchronizationManager.class里面的resources 的threadLocal 里面的connection,如果没有就为null
后面doBegin 方法里面最好是绑定数据源,就是存放在一个 ThreadLocal里面, 里面存放的是Map,key 就是 datasource,Value 就是对应的connection

	protected Object doGetTransaction() {
	    // 创建一个 DataSourceTransactionObject 对象
		DataSourceTransactionObject txObject = new DataSourceTransactionObject();
		// 设置 此事务中是否允许保存点, isNestedTransactionAllowed() 为true,是在事务创建时设置的
		txObject.setSavepointAllowed(isNestedTransactionAllowed());
		/**获取当前线程的connection 缓存,如果不存在,那就为null
		这里是一个Map 存储的, key 是datasource ,value 是connection
		**/
		ConnectionHolder conHolder =
				(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
		txObject.setConnectionHolder(conHolder, false);
		return txObject;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.7 AbstractPlatformTransactionManager#suspend

suspend 方法主要是对事务进行挂起,对于挂起操作主要的目的是记录原有事务的状态,以便后续操作对原有事务的恢复.

protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
        // 如果当前线程的事务同步器是否是活跃状态
		if (TransactionSynchronizationManager.isSynchronizationActive()) {
		    /** 这里获取所有事务同步器的 快照,先悬挂住,并把当前线程清空,最后返回一个 
		    new SuspendedResourcesHolder  对象
		    **/
			List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
			try {
				Object suspendedResources = null;
				if (transaction != null) {
					suspendedResources = doSuspend(transaction);
				}
				String name = TransactionSynchronizationManager.getCurrentTransactionName();
				TransactionSynchronizationManager.setCurrentTransactionName(null);
				boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
				TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
				Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
				TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
				boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
				TransactionSynchronizationManager.setActualTransactionActive(false);
				return new SuspendedResourcesHolder(
						suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
			}
			catch (RuntimeException | Error ex) {
				// doSuspend failed - original transaction is still active...
				doResumeSynchronization(suspendedSynchronizations);
				throw ex;
			}
		}
		else if (transaction != null) {
			// Transaction active but no synchronization active.
			Object suspendedResources = doSuspend(transaction);
			return new SuspendedResourcesHolder(suspendedResources);
		}
		else {
			// Neither transaction nor synchronization active.
			return null;
		}
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

2.8 AbstractPlatformTransactionManager#startTransaction

startTransaction方法 主要就是 开启新事务 ,详细逻辑在下面的doBegin

	private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
			boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {

		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		DefaultTransactionStatus status = newTransactionStatus(
				definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
				// 这里主要是构造transaction, 包括设置ConnectionHolder ,隔离级别,timeout ,如果是新连接,绑定到当前线程
		doBegin(transaction, definition);
		// 新同步事务的设置
		prepareSynchronization(status, definition);
		return status;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.9 DataSourceTransactionManager#doBegin

doBegin 主要是构造transaction, 包括设置ConnectionHolder ,隔离级别,timeout ,这类不是spring 完成,而是交给底层的数据连接去做的,如果是新连接,绑定到当前线程

protected void doBegin(Object transaction, TransactionDefinition definition) {
        // 转换为 DataSourceTransactionObject
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		Connection con = null;

		try {
		    // 如果没有数据连接connection
			if (!txObject.hasConnectionHolder() ||
					txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
				// 这里就是调用数据源进行获取 connection 并进行绑定
				Connection newCon = obtainDataSource().getConnection();
				if (logger.isDebugEnabled()) {
					logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
				}
				txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
			}

			txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
			con = txObject.getConnectionHolder().getConnection();
            // 对connection 设置 隔离级别和 是否只读属性
			Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
			txObject.setPreviousIsolationLevel(previousIsolationLevel);
			txObject.setReadOnly(definition.isReadOnly());

			// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
			// so we don't want to do it unnecessarily (for example if we've explicitly
			// configured the connection pool to set it already).
			/**
			这里就是关闭自动提交, 就是开启事务了,由Spring 控制提交
			**/
			if (con.getAutoCommit()) {
				txObject.setMustRestoreAutoCommit(true);
				if (logger.isDebugEnabled()) {
					logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
				}
				con.setAutoCommit(false);
			}
            /**
            设置只读事务,就是这事务内没有新增,修改,删除操作只有查询操作,不需要数据库锁等操作,减少数据库压力,
            还有就是其他事务提交的数据,在"SET TRANSACTION READ ONLY" 是看不到的
            **/
			prepareTransactionalConnection(con, definition);
			// 配置 判断当前线程是否有事务的 标志
			txObject.getConnectionHolder().setTransactionActive(true);
            // 设置timeout
			int timeout = determineTimeout(definition);
			if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
				txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
			}

			// Bind the connection holder to the thread.
			// 绑定这connection 到当前线程
			if (txObject.isNewConnectionHolder()) {
				TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
			}
		}

		catch (Throwable ex) {
			if (txObject.isNewConnectionHolder()) {
				DataSourceUtils.releaseConnection(con, obtainDataSource());
				txObject.setConnectionHolder(null, false);
			}
			throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
		}
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

2.10 TransactionAspectSupport#prepareTransactionInfo

当已经建立事务连接并完成了事务的提取后,我们需要将所有的事务信息统一记录在TransactionInfo 类型的实例里面,这个实例包含了目标方法开始前的所有状态信息,一旦事务执行失败,Spring 会通过TransactionInfo 类型的实例中的信息来进行回滚等后续工作.
方法prepareTransactionInfo 主要做了以下几件事:

  1. 创建了一个TransactionInfo 实例, 把tm,txAttr,joinpointIdentification,status 属性都填充进去了
  2. 先把之前的老的TransactionInfo 保存起来, 并把当前的TransactionInfo 放到ThreadLocal 里面暴露出去 ,这样就便于后续的
    还原,提交,回滚等一系列操作.
protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, String joinpointIdentification,
			@Nullable TransactionStatus status) {

		TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
		if (txAttr != null) {
			// We need a transaction for this method...
			if (logger.isTraceEnabled()) {
				logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
			}
			// The transaction manager will flag an error if an incompatible tx already exists.
			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.");
			}
		}

		// We always bind the TransactionInfo to the thread, even if we didn't create
		// a new transaction here. This guarantees that the TransactionInfo stack
		// will be managed correctly even if no transaction was created by this aspect.
		txInfo.bindToThread();
		return txInfo;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

三、小结

本章主要介绍了 创建事务相关的源码解析, 下一章介绍 事务的提交、回滚、异常处理等.

支付宝微信
支付宝微信
如果有帮助记得打赏哦特别需要您的打赏哦
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/225405?site
推荐阅读
相关标签
  

闽ICP备14008679号