前言
在上一篇文章 Spring源码解析--事务的详细讲解 中主要对Spring中事务的理论和实践作了详细整理,本文将透过现象看本质,从源码的角度入手分析下Spring中事务的实现原理及相关源码解析。
一、事务的相关组件
1.1、事务状态TransactionStatus
TransactionStatus是表示事务状态的接口,继承之SavepointManager和Flushable接口,源码如下:
1 public interface TransactionStatus extends SavepointManager, Flushable {
2
3 /**
4 * 判断事务是否是新事务
5 */
6 boolean isNewTransaction();
7
8 /**
9 * 判断事务是否含有保存点
10 */
11 boolean hasSavepoint();
12
13 /**
14 * 设置只可回滚
15 * 如果设置了rollback-only为true,那么只要抛异常就肯定会回滚,即使将异常捕获了也不可以提交
16 */
17 void setRollbackOnly();
18
19 /**
20 * 是否标记为只可回滚
21 * 如果设置了rollback-only为true,那么只要抛异常就肯定会回滚,即使将异常捕获了也不可以提交
22 */
23 boolean isRollbackOnly();
24
25 /**
26 * 刷新
27 */
28 @Override
29 void flush();
30
31 /**
32 * 事务是否完成
33 */
34 boolean isCompleted();
35
36 }
另外由于TransactionStatus继承之SavepointManager接口,所以实现类同样需要实现SavepointManager接口定义的方法,定义方法如下:
1 public interface SavepointManager {
2 /**
3 * 创建一个保存点
4 */
5 Object createSavepoint() throws TransactionException;
6
7 /**
8 * 回滚到保存点
9 */
10 void rollbackToSavepoint(Object savepoint) throws TransactionException;
11
12 /**
13 * 释放保存点
14 */
15 void releaseSavepoint(Object savepoint) throws TransactionException;
16 }
TransactionStatus接口的默认实现类为DefaultTransactionStatus类,构造方法及属性如下:
1 /** 当前事务对象 */
2 private final Object transaction;
3
4 /** 是否是新事务*/
5 private final boolean newTransaction;
6
7 /** 是否同步*/
8 private final boolean newSynchronization;
9
10 /** 是否为只读事务*/
11 private final boolean readOnly;
12
13 private final boolean debug;
14
15 private final Object suspendedResources;
16
17
18 /**
19 * 构造函数设置自身属性
20 */
21 public DefaultTransactionStatus(
22 Object transaction, boolean newTransaction, boolean newSynchronization,
23 boolean readOnly, boolean debug, Object suspendedResources) {
24
25 this.transaction = transaction;
26 this.newTransaction = newTransaction;
27 this.newSynchronization = newSynchronization;
28 this.readOnly = readOnly;
29 this.debug = debug;
30 this.suspendedResources = suspendedResources;
31 }
TransactionStatus持有一个事务的引用,并且包含当前事务的状态属性,所以每次创建一个事务时,都会被封装成一个TransactionStatus对象。而事务的创建则是通过事务管理器TransactionManager来管理的。
1.2、事务管理器TransactionManager
事务管理器是用于事务的管理,Spring中事务管理器通过接口PlatformTransactionManager定义,源码如下:
1 public interface PlatformTransactionManager {
2 /**
3 * 获取事务状态
4 */
5 TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
6
7 /**
8 * 提交事务
9 */
10 void commit(TransactionStatus status) throws TransactionException;
11
12 /**
13 * 回滚事务
14 */
15 void rollback(TransactionStatus status) throws TransactionException;
16 }
只定义了三个方法,分别是获取事务、提交事务和回滚事务,而这三个方法的实现通过AbstractPlatformTransactionManager抽象类来实现
1.2.1、获取事务状态方法getTransaction源码解析
1 /**
2 * 获取当前事务状态
3 * */
4 @Override
5 public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
6
7 /**
8 * 1.调用子类方法获取事务
9 * */
10 Object transaction = doGetTransaction();
11
12 if (definition == null) {
13 /** 如果没有传入参数,则创建默认事务 DefaultTransactionDefinition*/
14 definition = new DefaultTransactionDefinition();
15 }
16
17 /**
18 * 2.如果当前线程是否已经存在事务
19 * */
20 if (isExistingTransaction(transaction)) {
21 return handleExistingTransaction(definition, transaction, debugEnabled);
22 }
23
24 /******** 下面的逻辑都是当前线程不存在事务的情况 *******/
25
26 /**
27 * 3.判断当前事务是否已经超时
28 * */
29 if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
30 throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
31 }
32
33 /**
34 *
35 * 4.判断当前事务的传播机制,如果是MANDATORY类型且当前线程不存在事务,则抛异常处理
36 */
37 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
38 throw new IllegalTransactionStateException(
39 "No existing transaction found for transaction marked with propagation 'mandatory'");
40 }
41 else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
42 definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
43 definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
44 SuspendedResourcesHolder suspendedResources = suspend(null);
45 try {
46 boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
47 /**
48 * 5.创建一个新事务
49 * */
50 DefaultTransactionStatus status = newTransactionStatus(
51 definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
52 /**
53 * 6.开始事务
54 * */
55 doBegin(transaction, definition);
56 /**
57 * 7.初始化和同步事务
58 * */
59 prepareSynchronization(status, definition);
60 return status;
61 }
62 catch (RuntimeException ex) {
63 resume(null, suspendedResources);
64 throw ex;
65 }
66 catch (Error err) {
67 resume(null, suspendedResources);
68 throw err;
69 }
70 }
71 else {
72 if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
73 logger.warn("Custom isolation level specified but no actual transaction initiated; " +
74 "isolation level will effectively be ignored: " + definition);
75 }
76 boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
77 return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
78 }
79 }
1.2.2、提交事务方法commit源码解析
1 @Override
2 public final void commit(TransactionStatus status) throws TransactionException {
3 /** 1.如果事务已经完成,抛异常*/
4 if (status.isCompleted()) {
5 throw new IllegalTransactionStateException(
6 "Transaction is already completed - do not call commit or rollback more than once per transaction");
7 }
8
9 /**2. 如果事务需要回滚则执行 processRollback进行回滚*/
10 DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
11 if (defStatus.isLocalRollbackOnly()) {
12 if (defStatus.isDebug()) {
13 logger.debug("Transactional code has requested rollback");
14 }
15 processRollback(defStatus);
16 return;
17 }
18 if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
19 if (defStatus.isDebug()) {
20 logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
21 }
22 /** 3. 如果事务需要回滚,则执行回滚操作*/
23 processRollback(defStatus);
24 if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
25 throw new UnexpectedRollbackException(
26 "Transaction rolled back because it has been marked as rollback-only");
27 }
28 return;
29 }
30 /** 4.不需要回滚最终则执行提交逻辑*/
31 processCommit(defStatus);
32 }
最终执行回滚的逻辑是processCommit方法,源码如下:
1 private void processCommit(DefaultTransactionStatus status) throws TransactionException {
2 try {
3 boolean beforeCompletionInvoked = false;
4 try {
5 prepareForCommit(status);
6 triggerBeforeCommit(status);
7 triggerBeforeCompletion(status);
8 beforeCompletionInvoked = true;
9 boolean globalRollbackOnly = false;
10 if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
11 globalRollbackOnly = status.isGlobalRollbackOnly();
12 }
13 /**
14 * 1. 如果事务设置了保存点,则需要释放所有的保存点
15 * */
16 if (status.hasSavepoint()) {
17 if (status.isDebug()) {
18 logger.debug("Releasing transaction savepoint");
19 }
20 /** 释放事务的保存点*/
21 status.releaseHeldSavepoint();
22 }
23 else if (status.isNewTransaction()) {
24 if (status.isDebug()) {
25 logger.debug("Initiating transaction commit");
26 }
27 /** 2.提交事务 */
28 doCommit(status);
29 }
30 // Throw UnexpectedRollbackException if we have a global rollback-only
31 // marker but still didn't get a corresponding exception from commit.
32 if (globalRollbackOnly) {
33 throw new UnexpectedRollbackException(
34 "Transaction silently rolled back because it has been marked as rollback-only");
35 }
36 }
37 catch (UnexpectedRollbackException ex) {
38 // can only be caused by doCommit
39 triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
40 throw ex;
41 }
42 catch (TransactionException ex) {
43 // can only be caused by doCommit
44 if (isRollbackOnCommitFailure()) {
45 doRollbackOnCommitException(status, ex);
46 }
47 else {
48 triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
49 }
50 throw ex;
51 }
52 catch (RuntimeException ex) {
53 if (!beforeCompletionInvoked) {
54 triggerBeforeCompletion(status);
55 }
56 doRollbackOnCommitException(status, ex);
57 throw ex;
58 }
59 catch (Error err) {
60 if (!beforeCompletionInvoked) {
61 triggerBeforeCompletion(status);
62 }
63 doRollbackOnCommitException(status, err);
64 throw err;
65 }
66
67 // Trigger afterCommit callbacks, with an exception thrown there
68 // propagated to callers but the transaction still considered as committed.
69 try {
70 triggerAfterCommit(status);
71 }
72 finally {
73 triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
74 }
75
76 }
77 finally {
78 cleanupAfterCompletion(status);
79 }
80 }
最终执行doCommit方法,而doCommit方法是一个抽象方法,实际执行是通过AbstractPlatformTransactionManager的子类去实现,常用的子类使用的是DataSourceTransactionManager类,实
1 @Override
2 protected void doCommit(DefaultTransactionStatus status) {
3 DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
4 /**
5 * 1.获取事务的数据库连接
6 * */
7 Connection con = txObject.getConnectionHolder().getConnection();
8 if (status.isDebug()) {
9 logger.debug("Committing JDBC transaction on Connection [" + con + "]");
10 }
11 try {
12 /**
13 * 2.执行数据库连接的提交方法提交事务
14 * */
15 con.commit();
16 }
17 catch (SQLException ex) {
18 throw new TransactionSystemException("Could not commit JDBC transaction", ex);
19 }
20 }
1.2.3、回滚事务方法rollback源码解析
1 @Override
2 public final void rollback(TransactionStatus status) throws TransactionException {
3 if (status.isCompleted()) {
4 throw new IllegalTransactionStateException(
5 "Transaction is already completed - do not call commit or rollback more than once per transaction");
6 }
7
8 DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
9 /** 执行processRollback方法回滚事务 */
10 processRollback(defStatus);
11 }
processRollback方法和processCommit方法流程一样,最终调用doRollback方法,调用JDBC的数据库连接的rollback方法进行事务的回滚操作。
二、编程式事务源码解析
编程式事务逻辑比较清晰,因为事务是在业务代码中显示执行的,所以比较好理解,最常用的编程式事务采用的是事务模版,也就是TransactionTemplate模版类,TransactionTemplate实现了TransactionDefinition接口,主要作用是保存事务的全局配置,则通过事务管理的getTransaction(TransactionDefinition definition)方法获取到的事务属性都是一样的,使用方式如下:
1 @Override
2 public User addAndGet(User user, Long userId) {
3 return transactionTemplate.execute(new TransactionCallback<User>() {
4 @Override
5 public User doInTransaction(TransactionStatus status) {
6 userMapper.addUser(user);
7 return userMapper.getUserById(userId);
8 }
9 });
10 }
所以编程式事务的实现主要是通过TransactionTemplate的execute方法来实现的,所以可以直接从execute方法入手开始分析事务的实现方式。
1、TransactionTemplate的execute方法源码解析
1 /**
2 * 执行事务中的业务方法
3 * */
4 public <T> T execute(TransactionCallback<T> action) throws TransactionException {
5 if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
6 return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
7 }
8 else {
9 /**
10 * 1.获取当前事务的事务状态,其中transactionManager是配置的事务管理器TransactionManager实例
11 * */
12 TransactionStatus status = this.transactionManager.getTransaction(this);
13 T result;
14 try {
15 /**
16 * 2.执行具体的业务逻辑
17 * */
18 result = action.doInTransaction(status);
19 }
20 catch (RuntimeException ex) {
21 /** 业务抛RuntimeException异常则执行回滚*/
22 rollbackOnException(status, ex);
23 throw ex;
24 }
25 catch (Error err) {
26 /** 业务抛Error异常则执行回滚*/
27 rollbackOnException(status, err);
28 throw err;
29 }
30 catch (Throwable ex) {
31 /**
32 * 业务抛Throwable异常则执行回滚
33 * */
34 rollbackOnException(status, ex);
35 throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
36 }
37 /**
38 * 如果没有抛异常则执行提交事务
39 * */
40 this.transactionManager.commit(status);
41 return result;
42 }
43 }
44
45 /**
46 * 异常时回滚事务
47 * */
48 private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException {
49 try {
50 /**
51 * 执行事务管理器的rollback方法回滚事务
52 * */
53 this.transactionManager.rollback(status);
54 }
55 catch (TransactionSystemException ex2) {
56 logger.error("Application exception overridden by rollback exception", ex);
57 ex2.initApplicationException(ex);
58 throw ex2;
59 }
60 catch (RuntimeException ex2) {
61 logger.error("Application exception overridden by rollback exception", ex);
62 throw ex2;
63 }
64 catch (Error err) {
65 logger.error("Application exception overridden by rollback error", ex);
66 throw err;
67 }
68 }
通过编程式方式的事务流程比较清晰,主要就是通过调用事务管理器transactionManager的方法来实现,首先是调用getTransaction方法获取当前事务,然后尝试执行业务逻辑并捕获error和运行时异常,如果抛异常则执行事务管理器的回滚方法进行事务回滚。
如果没有抛异常则执行事务管理器的提交方法进行事务的提交。
三、声明式事务源码解析
声明式事务是通过Spring的AOP实现的,使用方法如下:
1 @Transactional
2 public User addAndGet(User user, Long userId) {
3 userMapper.addUser(user);
4 return userMapper.getUserById(userId);
5 }
熟悉AOP的实现流程的同学应该能够猜到,声明式事务的实现应该是拦截被@Transaction修饰的类或方法,然后通过创建增强的方式将事务的逻辑织入到业务代码中。
而解析@Transactional注解的织入事务逻辑在MethodInterceptor的实现类TransactionInterceptor中,所以被@Transactional注解修饰的方法,执行业务逻辑时都会执行TransactionInterceptor的invoke方法,源码如下:
1 @Override
2 public Object invoke(final MethodInvocation invocation) throws Throwable {
3 /**
4 * 1.获取拦截器的目标类
5 * */
6 Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
7
8 /**
9 * 将事务织入业务逻辑中
10 * */
11 return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
12 @Override
13 public Object proceedWithInvocation() throws Throwable {
14 return invocation.proceed();
15 }
16 });
17 }
1 protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
2 throws Throwable {
3
4 /** 1.获取事务设置的属性 */
5 final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
6 /** 2.获取事务管理器 */
7 final PlatformTransactionManager tm = determineTransactionManager(txAttr);
8 final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
9
10 if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
11 /** 3.创建TranscationInfo对象,相当于开启事务 */
12 TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
13 Object retVal = null;
14 try {
15 /** 4.执行被增强的方法 (业务逻辑)*/
16 retVal = invocation.proceedWithInvocation();
17 }
18 catch (Throwable ex) {
19 /** 5.异常之后回滚事务 */
20 completeTransactionAfterThrowing(txInfo, ex);
21 throw ex;
22 }
23 finally {
24 /** 6.finally中清除事务相关信息 */
25 cleanupTransactionInfo(txInfo);
26 }
27 /** 7. 业务逻辑执行完成之后提交事务 */
28 commitTransactionAfterReturning(txInfo);
29 return retVal;
30 }
31 }
声明式事务实现步骤总结如下:
1、将事务封装成AOP增强,拦截所有被@Transactional注解修饰的方法或类;或者通过标签<tx>配置的事务;将增强封装成方法拦截器TransactionInterceptor
2、添加事务的方法执行时,会执行增强拦截器TransactionInterceptor的invoke方法
3、先从配置中获取到事务的配置(传播机制、隔离机制、超时时间等)
4、从Spring容器中获取事务管理器PlatformTransactionManager的bean
5、调用事务管理器的getTransaction方法开启新事务
6、执行被拦截的业务逻辑,并进行try/catch捕获异常
7、如果捕获到异常,则执行事务管理器的rollback方法回滚事务
8、如果没有捕获异常,则执行事务管理器的commit方法提交事务
Tips:
不管是编程式事务还是声明式事务的实现,实际都是通过事务管理器来实现的,都是先通过事务管理器获取当前线程的事务,然后执行业务逻辑,如果异常需要回滚则执行事务管理器的回滚方法进行回滚,如果业务执行成功则执行事务管理器的提交方法提交事务。
而事务管理器的获取事务、回滚事务、提交事务又都是调用底层JDBC的数据库连接的相对应的方法来进行实现的,只不过是在数据库连接的获取事务、提交和回滚事务的方法之上进行了封装,使得业务代码使用事务时不需要关系底层JDBC的API