【spring】spring源码系列之十:spring事务管理(中)

系列文章目录

前言

上一篇自己简单实现了事务管理,接下来看看spring是如何实现的

一、spring的事务管理器DataSourceTransactionManager的使用

首先是配置类,配置了PlatformTransactionManager、jdbcTemplate和transactionTemplate

@Configuration
@ComponentScan("com.zcl.jdbc")
public class AppConfig {
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/j1910?characterEncoding=utf-8&useSSL=false");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean
    public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
        return new TransactionTemplate(transactionManager);
    }
}

然后是Dao层,updateWithTransaction1方法是一个简单的使用,抛错后会回滚前面所有操作;updateWithTransaction2方法是对事务传播的使用,updateSupports()报错后不会影响updateNew()的事务提交,但是会导致其他的回滚。

@Repository
public class StudentDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private TransactionTemplate transactionTemplate;

    /**不带事务*/
    public void updateStudent(int id, String name) {
        String sql = "update student set stu_name = ? where stu_id = ?";
        jdbcTemplate.update(sql, name, id);
    }
    /**简单使用*/
    public void updateWithTransaction1() {
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    updateStudent(7,"zhangsan");
                    updateStudent(8,"lisi");
                    int i = 1/0;
                    // 更多数据库操作...
                } catch (Exception e) {
                    status.setRollbackOnly(); // 触发回滚
                    throw e;
                }
            }
        });
    }
    /**事务的传播*/
    public void updateWithTransaction2() {
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    updateStudent(7,"required");//最终回滚
                    updateNew();//最终成功
                    updateSupports();//最终回滚
                } catch (Exception e) {
                    status.setRollbackOnly(); // 触发回滚
                    throw e;
                }
            }
        });
    }

    public void updateSupports() {
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    updateStudent(8,"supports");
                    int i = 1/0;
                } catch (Exception e) {
                    status.setRollbackOnly(); // 触发回滚
                    throw e;
                }
            }
        });
    }

    public void updateNew() {
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    updateStudent(9,"new");
                } catch (Exception e) {
                    status.setRollbackOnly(); // 触发回滚
                    throw e;
                }
            }
        });
    }
}

最后贴一点测试代码

public class MainTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        StudentDao studentDao = context.getBean(StudentDao.class);
        studentDao.updateWithTransaction2();
    }
}

二、spring的事务管理器DataSourceTransactionManager源码解析

上一篇介绍jdbc事务的使用、手写TransactionManager的使用都是为了抛砖引玉,是为了更好的分析DataSourceTransactionManager的源码。

我们在DataSourceTransactionManager的使用的例子中用到了3个关键的组件
JdbcTemplate
TransactionTemplate
DataSourceTransactionManager
下面逐个分析

1. JdbcTemplate

JdbcTemplate就是简化了数据库连接的获取关闭、sql的操作、结果集的封装,关键的方法如下:

public <T> T execute(StatementCallback<T> action) throws DataAccessException {
		Assert.notNull(action, "Callback object must not be null");

		Connection con = DataSourceUtils.getConnection(obtainDataSource());
		Statement stmt = null;
		try {
			stmt = con.createStatement();
			applyStatementSettings(stmt);
			T result = action.doInStatement(stmt);
			handleWarnings(stmt);
			return result;
		}
		catch (SQLException ex) {
			// Release Connection early, to avoid potential connection pool deadlock
			// in the case when the exception translator hasn't been initialized yet.
			String sql = getSql(action);
			JdbcUtils.closeStatement(stmt);
			stmt = null;
			DataSourceUtils.releaseConnection(con, getDataSource());
			con = null;
			throw translateException("StatementCallback", sql, ex);
		}
		finally {
			JdbcUtils.closeStatement(stmt);
			DataSourceUtils.releaseConnection(con, getDataSource());
		}
	}

我们主要看连接的获取DataSourceUtils.getConnection(obtainDataSource());

public static Connection doGetConnection(DataSource dataSource) throws SQLException {
		Assert.notNull(dataSource, "No DataSource specified");
		//从事务同步器中获取连接
		ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
		if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
			conHolder.requested();
			if (!conHolder.hasConnection()) {
				logger.debug("Fetching resumed JDBC Connection from DataSource");
				conHolder.setConnection(fetchConnection(dataSource));
			}
			return conHolder.getConnection();
		}
	logger.debug("Fetching JDBC Connection from DataSource");
		Connection con = fetchConnection(dataSource);

	...	
	}

从TransactionSynchronizationManager中获取连接,如果没有就重新从数据库获取连接。而TransactionSynchronizationManager中维护了一个ThreadLocal的map,所有事务相关的资源都放在这个map中,而ConnectionHolder就是以DataSource为key,以ConnectionHolder为value。所以这里获取连接就是从ThreadLocal中获取连接。

如果TranactionManager向ThreadLocal中存放了连接,那么JdbcTemplate执行sql是就能够ThreadLocal中获取到连接,那么就复用之前的连接(事务当然也是之前的事务),事务也就受TranactionManager管理了。如果TranactionManager没有向ThreadLocal中存放了连接,那么JdbcTemplate就获取不到连接,会新建自己的连接,执行完就提交事务了,事务也就不受TranactionManager管理了。所以TranactionManager管理事务的关键,就是执行sql时必须从ThreadLocal中获取到连接。所以现在应该明白为啥有时候事务会失效了吧(比如使用TransactionTemplate时没有使用jdbcTemplate,而是自己创建连接执行sql)。

private static final ThreadLocal<Map<Object, Object>> resources =
			new NamedThreadLocal<>("Transactional resources");

是不是很熟悉,跟我们手写的MyNewTransactionManager中获取连接的思路是不是一样

2.TransactionTemplate

TransactionTemplate内部维护了一个transactionManager,同时继承了DefaultTransactionDefinition,可以设置事务的一些属性,主要就是事务的传播方式和隔离级别

public class TransactionTemplate extends DefaultTransactionDefinition{
private PlatformTransactionManager transactionManager;
...
}

并提供了一个执行事务的方法,具体的事务由transactionManager完成,这个又与我们手写的MyTransactionTemplate一样

public <T> T execute(TransactionCallback<T> action) throws TransactionException {
		Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");

		if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
			return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
		}
		else {
			TransactionStatus status = this.transactionManager.getTransaction(this);
			T result;
			try {
				result = action.doInTransaction(status);
			}
			catch (RuntimeException | Error ex) {
				// Transactional code threw application exception -> rollback
				rollbackOnException(status, ex);
				throw ex;
			}
			catch (Throwable ex) {
				// Transactional code threw unexpected exception -> rollback
				rollbackOnException(status, ex);
				throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
			}
			this.transactionManager.commit(status);
			return result;
		}
	}

3.DataSourceTransactionManager

根据上面TransactionTemplate的execute方法的执行过程来看看DataSourceTransactionManager的主要源码

3.1 获取事务、挂起事务和开启事务

TransactionStatus status = this.transactionManager.getTransaction(this);
代码如下:

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

		// Use defaults if no transaction definition given.
		TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
		//新建一个事务对象,并从TransactionSynchronizationManager中获取ConnectionHolder,设置到这个事务对象中,获取的ConnectionHolder用于后续判断是否存在上层事务
		Object transaction = doGetTransaction();
		boolean debugEnabled = logger.isDebugEnabled();

		//如果存在上层事务,处理上层事务
		if (isExistingTransaction(transaction)) {
			// Existing transaction found -> check propagation behavior to find out how to behave.
			return handleExistingTransaction(def, transaction, debugEnabled);
		}
		...
		//根据传播方式,来决定是否开启事务
		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);
		}
	}

先介绍一个组件,因为后面会频繁提到

DataSourceTransactionObject: 事务对象,封装了ConnectionHolder和newConnectionHolder属性,ConnectionHolder是对连接的封装,其中有个非常重要的属性rollbackOnly,这个属性与我们手写MyNewTransactionManager时的rollbackOnly类似,是全局判断是否需要回滚的标记。 newConnectionHolder用于判断是否是新建的连接,如果是就要绑定到ThreadLocal中,同时在清理事务的时候将连接从ThreadLocal中解绑。当然DataSourceTransactionObject还有其他几个属性,比如是否允许设置保存点、保存上一层事务的隔离级别等,用于实现一些功能,从字面意思上就能理解,就不展开了,自己要用到的时候再来扒源码。现在只需要记住ConnectionHolder和newConnectionHolder就可以了

private boolean newConnectionHolder;
private boolean mustRestoreAutoCommit;
private ConnectionHolder connectionHolder;
private Integer previousIsolationLevel;
private boolean readOnly = false;
private boolean savepointAllowed = false;

再来看上面那段代码的逻辑:
1)新建一个事务对象,并从TransactionSynchronizationManager中获取ConnectionHolder,设置到这个事务对象中,获取的ConnectionHolder用于后续判断是否存在上层事务
2)判断这个事务对象中是否存在事务,如果存在,根据传播方式处理存在的事务。源码不难看懂,我就不贴代码了,逻辑如下
a.如果是NEVER,抛错
b.如果是NOT_SUPPORTED,挂起当前事务对象,不开启新的事务(新建一个事务对象为空的DefaultTransactionStatus返回)
c.如果是NEW,挂起当前事务对象,开启新事务(新建一个事务对象为新事务的DefaultTransactionStatus返回)
d.如果是NESTED,设置保存点(新建一个复用上层事务的DefaultTransactionStatus返回)
e.如果是SUPPORTS和REQUIRED,加入现有事务(新建一个复用上层事务的DefaultTransactionStatus返回)
3)如果不存在,根据传播方式,来决定是否开启事务
a.如果是REQUIRED、NEW、NESTED,挂起空事务,开启新事务(新建一个事务对象为新事务的DefaultTransactionStatus返回)
b.如果是其他的,不开启新的事务(新建一个事务对象为空的DefaultTransactionStatus返回)

这里的逻辑就是我们对spring事务的6种传播方式的理解。我们要剖析这个背后是怎么实现的,那么就需要搞清楚三个内容,一是挂起事务,二是开启事务,三是返回的DefaultTransactionStatus是什么?

我们先来看挂起事务
上面提到了两种,一是挂起当前事务,二是挂起空事务。区别就是挂起的事务对象是否为空

protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
		//如果事务同步器中synchronizations中的set集合不为null,挂起生命周期方法
		if (TransactionSynchronizationManager.isSynchronizationActive()) {
			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)如果事务同步器中synchronizations中的set集合不为null(什么时候不为null呢,就是开启事务后初始化了),那么挂起set集合中的生命周期方法,挂起事务中的连接(如果连接不为空的话);挂起事务的名称、当前事务是否只读、当前事务隔离级别。其中生命周期方法就是每次提交、回滚事务前后、挂起恢复前后需要执行的方法,调用者直接在TransactionSynchronizationManager设置即可。

private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class);
	//这个资源主要就是ConnectionHolder
	private static final ThreadLocal<Map<Object, Object>> resources =
			new NamedThreadLocal<>("Transactional resources");
	//生命周期方法
	private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
			new NamedThreadLocal<>("Transaction synchronizations");
	//事务的名称
	private static final ThreadLocal<String> currentTransactionName =
			new NamedThreadLocal<>("Current transaction name");
	//当前事务是否只读
	private static final ThreadLocal<Boolean> currentTransactionReadOnly =
			new NamedThreadLocal<>("Current transaction read-only status");
	//当前事务隔离级别
	private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
			new NamedThreadLocal<>("Current transaction isolation level");
	//是否激活
	private static final ThreadLocal<Boolean> actualTransactionActive =
			new NamedThreadLocal<>("Actual transaction active");

2)如果没有生命周期的方法synchronizations ,那么就只需要挂起事务(就是ConnectionHolder)。
3)如果既没有生命周期的方法也没有事务,那么就返回null
挂起就是将全局对象(各种ThreadLocal)中的值置为null或者还原为初始值,将被挂起的对象组成一个对象SuspendedResourcesHolder返回,保存在新建的TransactionStatus对象中,等待后续恢复事务

//返回当前的事务信息
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
//放到新建的TransactionStatus对象中,等待后续恢复事务
DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
				
			}

再来看开启事务
如果是开启新事务,都会调用下面的代码:

	DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
	doBegin(transaction, definition);
	prepareSynchronization(status, definition);

如果是不开启新事务

	DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
	doBegin(transaction, definition);
	prepareSynchronization(status, definition);

1)doBegin:就是新建连接、绑定连接到ThreadLocal、设置autocommit为false、设置read-only和隔离级别。如果不开启事务,这一步就没有
2)prepareSynchronization:初始化事务同步器,将@transactional中配置的隔离级别、ReadOnly、name设置到ThreadLocal中,然后给synchronizations设置一个空的set集合

再来看TransactionStatus对象

也就是TransactionStatus status = this.transactionManager.getTransaction(this)最后返回的对象。直接返回事务对象DataSourceTransactionObject就好了啊,为什么还要封装一层?当然是为了增加功能,其实刚刚讲挂起事务就能知道TransactionStatus的部分作用了(保存了事务信息啊),前面讲过事务对象DataSourceTransactionObject的结构,而TransactionStatus就是对DataSourceTransactionObject的封装

**DefaultTransactionStatus:**事务状态,对事务对象的进一步封装。结构如下:

//事务对象
private final Object transaction;
//是否是新的事务
private final boolean newTransaction;
private final boolean newSynchronization;
//挂起的同步信息
private final Object suspendedResources;
//是否回滚
private boolean rollbackOnly = false;
private boolean completed = false;
//保存点
private Object savepoint;

主要有四个功能:
a. newTransaction用于判断是否是新的事务,决定后续如果提交和回滚事务(跟我们手写TransactionObject中的newConnection作用差不多)
b. suspendedResources用于保存被挂起事务的资源
c. savepoint用于设置保存点。
d. rollbackOnly用于手动标记回滚。我们一般认为抛错了才会回滚,但这里让程序员自己根据业务决定是否回滚,也就是说,即使事务执行没有报错,程序员可以自己手动将rollbackOnly设置为true,从而使事务回滚。写一下代码示例解释一下,如下,没有报错但是最后能够回滚

transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                  Student stu = queryStudent(9,"new");
                  if (stu == null){
                  	status.setRollbackOnly(); // 受到触发回滚
                  }
                } catch (Exception e) {
                  e.printStackTrace();
                }
            }
        });

3.2 执行sql

result = action.doInTransaction(status);
这个就不用讲了,这个是调用者自己实现的,调用者可以给TransactionStatus设置一些值,比如将localRollbackOnly设置为true

3.3 回滚事务

rollbackOnException(status, ex);
这个方法其实就是调用的transactionManager.rollback方法,部分代码如下:

private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
		try {
				...
				//如果有保存点
				if (status.hasSavepoint()) {
					if (status.isDebug()) {
						logger.debug("Rolling back transaction to savepoint");
					}
					status.rollbackToHeldSavepoint();
				}
				//如果是新的事务
				else if (status.isNewTransaction()) {
					if (status.isDebug()) {
						logger.debug("Initiating transaction rollback");
					}
					doRollback(status);
				}
				//如果不是新的事务
				else {
					// Participating in larger transaction
					if (status.hasTransaction()) {
						if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
							doSetRollbackOnly(status);
						}
					}
				}
				...
				finally {
			cleanupAfterCompletion(status);
		}
			}

这个逻辑就很简单的,跟我们自己写的MyNewTransactionManager差不多啊
1)如果有保存点,回滚到保存点(NESTED传播方式)
2)如果是新的事务,提交事务
3)如果不是新的事务,将ConnectionHolder的rollbackOnly属性设为true
4)最后进行清理,这一步很重要,不要忽略,因为除了清理当前的一些资源以外,还将之前挂起的事务还原了,具体如下:
a.如果是新建连接,从threadlocal中解绑,释放连接
b.如果有挂起的上层事务,恢复上层事务

private void cleanupAfterCompletion(DefaultTransactionStatus status) {
		status.setCompleted();
		//这个先不管
		if (status.isNewSynchronization()) {
			TransactionSynchronizationManager.clear();
		}
		//如果是新建连接,从threadlocal中解绑,释放连接
		if (status.isNewTransaction()) {
			doCleanupAfterCompletion(status.getTransaction());
		}
		//如果有挂起的上层事务,恢复上层事务
		if (status.getSuspendedResources() != null) {
			if (status.isDebug()) {
				logger.debug("Resuming suspended transaction after completion of inner transaction");
			}
			Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
			resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
		}
	}

3.4 提交事务

this.transactionManager.commit(status);

public final void commit(TransactionStatus status) throws TransactionException {
		...
		DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
		//如果localRollbackOnly为true
		if (defStatus.isLocalRollbackOnly()) {
			if (defStatus.isDebug()) {
				logger.debug("Transactional code has requested rollback");
			}
			processRollback(defStatus, false);
			return;
		}
		//shouldCommitOnGlobalRollbackOnly默认为false,这里为true时就要手动去设置localRollbackOnly的值,我们一般用不到就不展开了
		if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
			if (defStatus.isDebug()) {
				logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
			}
			processRollback(defStatus, true);
			return;
		}

		processCommit(defStatus);
	}

我们只需要关注主流程,processCommit(defStatus);
关键代码如下:

private void processCommit(DefaultTransactionStatus status) throws TransactionException {
		try {
			...
				if (status.hasSavepoint()) {
					unexpectedRollback = status.isGlobalRollbackOnly();
					status.releaseHeldSavepoint();
				}
				else if (status.isNewTransaction()) {
					unexpectedRollback = status.isGlobalRollbackOnly();
					doCommit(status);
				}
			}catch(
			...
			}
		finally {
			cleanupAfterCompletion(status);
		}

1)如果有保存点,释放保存点,因为执行到这里肯定是没有报错的,保存点已经没有用了
2)如果是新事务,提交事务
3)如果不是新事务,什么都不干
4)最后进行清理

if (status.getSuspendedResources() != null) {
			Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
			resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
		}

3.5 小结

根据上面介绍,TransactionTemplate使用DataSourceTransactionManager管理事务的流程大致如下:

  1. 获取上层事务:很显然,第一次开启事务时为空,在事务中调用事务时才会有
  2. 挂起上层事务:挂起上层事务资源(连接、事务名称、事务传播方式、事务隔离级别、事务的生命周期方法),根据事务的传播方式来决定是挂起还是加入
  3. 开启本层事务:根据事务的传播方式来决定是否开启事务。如果是新建连接,还要绑定到ThreadLocal中
  4. 执行本层事务
  5. 提交或回滚事务:如果是新开启事务才会真正去提交和回滚,根据TransactionStatus的rollbackOnly属性(本层事务所有)、ConnectionHolder的rollbackOnly属性(全局所有),提交或回滚;如果不是新开启的事务,只会对ConnectionHolder的rollbackOnly属性进行标记。
  6. 然后清理当前事务,恢复挂起的上层事务
    在这里插入图片描述

4. 问题

  1. 怎么理解事务是一层一层的?
    每个事务方法执行的时候都会创建TransactionStatus用于记录当前事务的状态,例如当事务方法A调用事务方法B时,会将A的各种状态保存在B的TransactionStatus中,如果事务B又调用了事务C,以此类推,形成一个链表。执行完一个事务再根据链表回复前面的事务,所以是一层层的

总结

我们通过TransactionTemplate的使用,解读了DatasourceTransactionManager的源码
1)讲解了TransactionObject的结构,TransactionObject封装了ConnectionHolder,ConnectionHolder中有rollbackOnly标记。如果上下层事务是同一个事务,那么ConnectionHolder以及其中的rollbackOnly标记就是全局的。
2)讲解了TransactionStatus的结构,TransactionStatus封装了连接和被挂起的事务,并通过newTransaction这个标记用于决定是真正提交、回滚,还是对ConnectionHolder中的rollbackOnly进行标记
3)讲解了TransactionSynchronizationManager的结构,用于保存连接和被挂起的事务,从而能够实现事务的挂起和恢复
4)讲解了事务执行的整个流程:获取上层事务->挂起上层事务->开启本层事务->执行本层事务->提交和回滚事务->清理本层事务和恢复上层事务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值