目录

17 声明式事务执行流程源码分析

spring源码系列文章,示例代码的中文注释,均是 copy 自 https://gitee.com/wlizhi/spring-framework

链接中源码是作者从 github 下载,并以自身理解对核心流程及主要节点做了详细的中文注释。


1 执行入口

声明式事务中XML配置及注解方式的注册入口 中,已经详细列举了事务注入入口的源码。

其中主要有三个比较关键的类:

  • BeanFactoryTransactionAttributeSourceAdvisor 增强类,其中封装了Advice,以及TransactionAttributeSource
  • TransactionAttributeSource 元数据检索的策略接口,对@Transactional的解析类支持,就在这里面封装。
  • TransactionInterceptor Advice实现,也是一个MethodInterceptor,具体的通知方法的执行就在这里面定义的。

在AOP生成代理实例时,会将所有搜集、或转换封装好的Advisor,缓存到AdvisedSupport.advisors中。

在第一次执行代理方法的时候,会遍历所有的Advisor,根据PointCut对方法进行匹配。匹配成功的,就添加到执行链,并缓存到AdvisedSupport.methodCache。后面再调用代理方法,就会优先从缓存中获取。

那么,BeanFactoryTransactionAttributeSourceAdvisor中,一定封装了PointCut。源码中是这样定义的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
	private TransactionAttributeSource transactionAttributeSource;
	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
		@Override
		@Nullable
		protected TransactionAttributeSource getTransactionAttributeSource() {
			return transactionAttributeSource;
		}
	};
}

如果一个方法开启了事务,最终在getBean的时候,获取到的一定是代理对象。当第一次调用时,会生成执行链,并按执行链中的节点索引顺序来执行。事务的MethodInterceptor就是其中的一个节点。

既然 TransactionInterceptor 是一个 MethodInterceptor,那它一定实现了 invoke(),事务的执行入口,就在这个invoke()里面。

以下是 invoke() 的源码:

1
2
3
4
5
6
7
8
9
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

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

2 主流程概览

进入到 invokeWithinTransaction() 的源码:

 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
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
    protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {
		/*
		 * TODO 其中事务传播行为的特点(这些特点,仔细分析代码是可以看出来的。相对比较烧脑。一般先了解特点,后面才会看源码):
		 *  PROPAGATION_REQUIRED 如果当前存在事务,假如当前事务。如果不存在事务,新建事务。
		 *  PROPAGATION_REQUIRES_NEW 如果当前存在事务,则挂起当前事务,新建一个事务。如果不存在事务,新建一个事务。使用频率高
		 *  PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前不存在事务,则和PROPAGATION_REQUIRED一样新建事务。
		 *      特点:外围事务回滚,嵌套事务全部回滚。嵌套事务回滚,如果在外围中捕获了,则仅仅回滚嵌套事务。
		 *  PROPAGATION_MANDATORY 以事务方式运行,如果当前不存在事务,则抛出异常
		 *  PROPAGATION_NEVER 以非事务方式运行,如果当前存在事务,则抛出异常
		 *  PROPAGATION_SUPPORTEDS 支持事务。如果当前存在事务,加入当前事务。如果不存在事务,则以非事务方式运行。
		 *  PROPAGATION_NOT_SUPPORTED 以非事务方式运行。如果当前存在事务,挂起当前事务。
		 */

		// 事务属性的获取
		// If the transaction attribute is null, the method is non-transactional.
		TransactionAttributeSource tas = getTransactionAttributeSource();
		// TODO getTransactionAttribute中是获取事务注解属性的具体逻辑。
		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)) {
			// TODO 重点:如果有必要,创建事务
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
			Object retVal = null;
			try {
				// 上层方法中传入的回调函数,这里面是AOP执行链,火炬传递,直到调用了业务方法
				// 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 {
				// TODO 清除事务信息,将当前事务清除,如果存在旧的事务对象,将旧的事务对象设置为当前持有的事务
				//  存储在TransactionAspectSupport.transactionInfoHolder中,这是一个静态TrheadLocal常量。
				cleanupTransactionInfo(txInfo);
			}
			// TODO 提交事务
			commitTransactionAfterReturning(txInfo);
			return retVal;
		} else {
			// 此处省略...
		}
	}
}

上面源码中,注释了前文中列举的spring声明式事务中的七种事务传播行为,以及它们的表现形式。

从源码中可以看出事务的主要流程:

  1. 获取到 TransactionAttributeSource。这个类封装了事务注解的解析操作。
  2. 根据第一步获取的结果,调用 getTransactionAttribute(),获取方法中的事务属性。
  3. 获取到方法的定义,实际上就是当前方法的全路径名。方法的描述在 TransactionAttribute 中有封装。
  4. 如果有必要,就创建事务。是否有必要、要看方法上是否有 @Transactional 注解,以及传播行为配置。当然,<tx:advice/> 这种全局配置也是。
  5. 执行被代理方法,即真正的业务方法。
  6. 如果抛出异常,按照抛出异常的处理方式,处理提交或回滚事务,将异常向上抛出。(抛出异常只是有可能会回滚,默认Error和RuntimeException会回滚,可以配置。)
  7. 清楚事务信息。如果存在旧的事务对象,将旧的事务对象设置为当前持有的事务对象。
  8. 提交事务。

如果看源码细节的话,这是一个很长的流程,要整体串联起来看。

3 传播行为的实现原理

进入到 createTransactionIfNecessary(),看一下源码中怎么做的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {

    protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
        // 省略...
		TransactionStatus status = null;
		if (txAttr != null) {
			if (tm != null) {
				// TODO 重点:获取TransactionStatus对象
				//  无论被代理对象的方法是否需要事务,在通过代理对象调用方法时,总会创建一个TransactionStatus,讲一些信息绑定到
				//  TrheadLocal的缓存变量中。这是为了在执行完方法的时候,可以回溯到调用方法存在的事务对象。类似责任链。
				//  如果挂起了存在的事务,则当前方法执行的事务状态对象中会存储SuspendedResourcesHolder,及挂起的事务信息,
				//  当方法执行完后,将这个挂起从新设置到当前事务中来。
				status = tm.getTransaction(txAttr);
			}
			// 省略...
		}
		// TODO 重点:将上面获取到的对象封装成TransactionInfo对象
		return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
	}
}

源码内容很简单,首先获取事务,封装成 TransactionStatus,然后将 TransactionStatus 封装成 TransactionInfo 返回。

3.1 前一个方法未开启事务时的处理

重点来到 getTransaction(),这里定义了针对不同的传播行为,做了不同的处理:

源码如下:

 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
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
    @Override
	public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
		// 获取事务对象
		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();
		}

		// 判断是否已经存在事务。如果当前事务对象已经持有了链接,并且事务是活跃状态,则表示已经存在事务。
		// 如果当前已经存在事务,按照已存在事务的方式判断传播行为,进行处理
		if (isExistingTransaction(transaction)) {
			// Existing transaction found -> check propagation behavior to find out how to behave.
			// TODO 如果当前已存在事务,会走到此方法逻辑进行处理。
			return handleExistingTransaction(definition, transaction, debugEnabled);
		}
		// TODO 以下是针对前一个方法未开启事务的情况的处理。

		// 检测事务的超时时间设置是否正确
		// Check definition settings for new transaction.
		if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
		}

		// 如果传播属性是PROPAGATION_MANDATORY,且当前不存在事务,则抛出异常
		// No existing transaction found -> check propagation behavior to find out how to proceed.
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}// 如果传播属性是PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED时,会走到这里
		else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			// 因为以上三种事务传播属性的特性,这里会挂起(如果当前存在事务)
			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);
				// TODO 重点:开启事务。按照当前测试代码注册的事务管理器,使用的是DataSourceTransactionManager
				doBegin(transaction, definition);
				// 如果是新开启的事务,设置事务管理器相关属性。其实走到这里的代码,一定是新启的事务。
				// 因为前面已经判断了,如果存在事务,就走handleExistingTransaction方法
				prepareSynchronization(status, definition);
				return status;
			}
			catch (RuntimeException | Error ex) {
				resume(null, suspendedResources);
				throw ex;
			}
		}
		else {
			// 以非事务方式运行 NEVER SUPPORTS NOT_SUPPORTED,在外围未开启事务时,会走这里。
			// 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);
		}
	}
}

从上面源码中可以看到,getTransaction() 主要分为两个部分:

  1. 针对前一个方法(调用当前代理方法的方法),已经开启了事务的处理方式。
  2. 针对前一个方法,未开启事务的处理方式。

先看前一个方法未开启事务时,看以上源码中是怎么处理的。

  1. 检测事务的超时时间设置是否正确。(不能小于-1)
  2. 如果传播行为是 PROPAGATION_MANDATORY,直接抛出异常。(这也验证了,传播行为是 MADATORY 时,如果外围方法未开启事务,就抛出异常的行为。)
  3. 如果传播行为是 PROPAGATION_REQUIRED/PROPAGATION_REQUIRES_NEW/PROPAGATION_NESTED时,就挂起前一个事务(注意方法参数是null,也就是并没有事务挂起),然后调用 doBegin(),开启新的事务。 这三种传播行为,在前一个方法未开启事务时,都会新启一个事务。
  4. 如果传播行为是其余几种,则以非事务方式运行。所以参数中的事务对象传递的是null。

还有一个 prepareSynchronization 处理,这个是事务同步器的内容。它是对事务功能的扩展,可以在事务提交、异常回滚、及其他动作节点插入自定义的操作。在别的文章中列举。

3.2 判断前一个方法是否开启事务

上面源码中第一个方法 doGetTransaction(),是创建一个 DataSourceTransactionObject,在其中封装 ConnectionHolder,这个 ConnectionHolder 是从 TransactionSynchronizationManager中一个线程绑定的变量中获取的。 如果前一个方法开启了事务,它是有值的。

判断前一个方法中是否开启了事务正式基于此,如果 ConnectionHolder 有值,且 active 是true,说明它是开启了事务的。

以下是 doGetTransaction() 源码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public abstract class TransactionSynchronizationManager {
	private static final ThreadLocal<Map<Object, Object>> resources =
			new NamedThreadLocal<>("Transactional resources");
	private static Object doGetResource(Object actualKey) {
		Map<Object, Object> map = resources.get();
		if (map == null) {
			return null;
		}
		Object value = map.get(actualKey);
		if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
			map.remove(actualKey);
			if (map.isEmpty()) {
				resources.remove();
			}
			value = null;
		}
		return value;
	}
}

resource是一个与线程绑定的map,之所以要用map,是因为一个线程多个方法调用栈内,可能有多个数据源,它的键值就跟数据源相关。

判断前一个方法是否开启了事务的源码:

1
2
3
4
5
6
7
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {
	protected boolean isExistingTransaction(Object transaction) {
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
	}
}

doGetTransaction() 中创建了一个DataSourceTransactionObject,内部封装了 ConnectionHolder,这个 ConnectionHolder 与线程绑定,所以在这里根据获取到的 ConnectionHolder,判断是否存在,且事务状态活跃。根据判断结果来确定前一个方法是否存在事务。

3.3 前一个方法开启事务时的处理

这段逻辑在 handleExistingTransaction(),源码如下:

 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
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
	private TransactionStatus handleExistingTransaction(
			TransactionDefinition definition, Object transaction, boolean debugEnabled)
			throws TransactionException {

		// 如果当前方法传播属性为从不开启事务,直接抛出异常。
		// PROPAGATION_NEVER特性决定,如果当前存在事务,则抛出异常
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
			throw new IllegalTransactionStateException(
					"Existing transaction found for transaction marked with propagation 'never'");
		}

		// PROPAGATION_NOT_SUPPORTED特性:如果当前存在事务,挂起当前事务,以非事务方式运行
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
			if (debugEnabled) {
				logger.debug("Suspending current transaction");
			}
			// 挂起事务
			Object suspendedResources = suspend(transaction);
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			// 返回事务状态对象
			return prepareTransactionStatus(
					definition, null, false, newSynchronization, debugEnabled, suspendedResources);
		}

		// TODO 重点:PROPAGATION_REQUIRES_NEW特性:无论当前是否存在事务,都新建一个事务。
		//  如果存在事务,将会把当前事务挂起,被挂起的事务会存储到新的事务状态对象中。
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
			if (debugEnabled) {
				logger.debug("Suspending current transaction, creating new transaction with name [" +
						definition.getName() + "]");
			}
			// 挂起当前事务,由于PROPAGATION_REQUIRES_NEW的特性,需要使用新的事务,所以要将当前事务挂起,当新的事务执行完毕时,会恢复这个挂起的事务。
			SuspendedResourcesHolder suspendedResources = suspend(transaction);
			try {
				boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
				// TODO 可以看到,这里创建事务对象时,构造函数中的参数newTransaction为true。
				DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
				// PROPAGATION_REQUIRES_NEW表示总是新启一个事务,这里会新开启事务。
				doBegin(transaction, definition);
				prepareSynchronization(status, definition);
				return status;
			}
			catch (RuntimeException | Error beginEx) {
				resumeAfterBeginException(transaction, suspendedResources, beginEx);
				throw beginEx;
			}
		}

		// TODO PROPAGATION_NESTED嵌套事务,如果存在事务,则在嵌套事务中运行。如果不存在事务,则新建一个事务。
		//  嵌套事务是用savePoint来实现的。具体过程:
		//  1.新建事务状态对象时,会设置一个保存点(或者叫回滚点)。
		//  2.如果业务方法执行抛出异常,则会被事务切面捕获,如果存在保存点,则会回滚值保存点。
		//  3.正常执行完业务方法,如果这个方法对应的事务状态对象中具有保存点,则会擦除这个保存点。
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			if (!isNestedTransactionAllowed()) {
				throw new NestedTransactionNotSupportedException(
						"Transaction manager does not allow nested transactions by default - " +
						"specify 'nestedTransactionAllowed' property with value 'true'");
			}
			if (debugEnabled) {
				logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
			}
			// 是否使用保存点,在测试中用到的事务管理器来看,总是返回true
			if (useSavepointForNestedTransaction()) {
				// Create savepoint within existing Spring-managed transaction,
				// through the SavepointManager API implemented by TransactionStatus.
				// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
				DefaultTransactionStatus status =
						prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
				// 创建savePoint,保存点(或者叫回滚点)
				status.createAndHoldSavepoint();
				return status;
			}
			else {
				boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
				DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, true, newSynchronization, debugEnabled, null);
				doBegin(transaction, definition);
				prepareSynchronization(status, definition);
				return status;
			}
		}

		// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
		if (debugEnabled) {
			logger.debug("Participating in existing transaction");
		}
		// 省略无关代码...
		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		// 创建事务状态对象,如果是新创建的事务,则设置事务管理器的相关属性。
		return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
	}
}

源码中的流程:

  1. 如果方法中事务传播行为设置的是 PROPAGATION_NEVER,就抛出异常。(这也验证了,NEVER 传播行为,如果当前存在事务就抛出异常的行为。)
  2. 如果传播行为是 PROPAGATION_NOT_SUPPORTED,就挂起已存在的事务,创建TransactionStatus时,事务对象参数传递的是null。
  3. 如果传播行为是 PROPAGATION_REQUIRES_NEW,就挂起已存在的事务,并创建新的 TransactionStatus,这个TransactionStatus中封装了SuspendedResourcesHolder,这是前一个方法的事务信息,会在当前方法执行完毕后,还原为原来的事务对象。这里开启新的事务对象,是会重新获取连接的。
  4. 如果传播行为是 PROPAGATION_NESTED,创建 TransactionStatus 时,将已存在的事务封装进去,并标记一个回滚点。设置了回滚点的TransactionStatus,回滚时,只会回滚到这个标记处。
  5. 如果传播行为是其他的类型,调用prepareTransactionStatus,使用已存在的事务对象,包装成TransactionStatus,即加入到已存在的事务中。

4 事务的开启

从上面的代码中,已经知道了事务开启是通过 doBegin()。

以下是 doBegin() 源码:

 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
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {
    protected void doBegin(Object transaction, TransactionDefinition definition) {
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		Connection con = null;

		try {
			// 如果当前事务对象没有持有链接,就获取一个,并设置到链接持有变量中。
			if (!txObject.hasConnectionHolder() ||
					txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
				Connection newCon = obtainDataSource().getConnection();
				if (logger.isDebugEnabled()) {
					logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
				}
				txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
			}
			// 设置事务同步为true,标识使用了事务。
			txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
			// 获取数据库连接对象。
			con = txObject.getConnectionHolder().getConnection();

			// 设置事务隔离级别
			Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
			txObject.setPreviousIsolationLevel(previousIsolationLevel);

			// TODO 重点:开启事务核心点:将事务自动提交关闭。即手动提交事务(由spring控制事务提交)
			// 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).
			if (con.getAutoCommit()) {
				txObject.setMustRestoreAutoCommit(true);
				if (logger.isDebugEnabled()) {
					logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
				}
				con.setAutoCommit(false);
			}

			// 如果Transaction中配置了只读,这里会将事务设置为只读属性
			prepareTransactionalConnection(con, definition);
			// 在事务链接持有对象中,设置事务活跃状态为true
			txObject.getConnectionHolder().setTransactionActive(true);

			// 查找配置的事务超时时间,如果未配置,会使用默认的。默认值为-1,表示永不超时。
			int timeout = determineTimeout(definition);
			if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
				// 在链接持有对象中设置超时时间,从这里可以看出,单位是秒。
				txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
			}

			// 如果事务对象是在当前代理方法中new的,则绑定到ThreadLocal变量中。
			// Bind the connection holder to the thread.
			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);
		}
	}
}

方法第一次执行时,肯定是没有连接的。首先,获取到一个数据库连接。并将这个链接封装成 ConnectionHolder,添加到 DataSourceTransactionObject 中。

获取到链接对象,设置事务隔离级别、超时时间等信息。最关键的一行代码是 con.setAutoCommit(false),将自动提交关闭,改为手动提交事务。在后面的流程,调用代理方法后,根据执行结果进行事务提交或回滚。