1.引
上一节已经分析了了在单service单方法下的事物创建过程以及其后续处理工作,当然还缺少真正创建事物的分析,本篇接续。先来回顾一下事物创建的代码片段:
try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); // 创建DefaultTransactionStatus对象实例 DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); // 开启事物 doBegin(transaction, definition); // 初始化事务同步。 prepareSynchronization(status, definition); return status; }
2.创建DefaultTransactionStatus对象
/** * 创建DefaultTransactionStatus实例 * Create a TransactionStatus instance for the given arguments. */ protected DefaultTransactionStatus newTransactionStatus( TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction, boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) { boolean actualNewSynchronization = newSynchronization && !TransactionSynchronizationManager.isSynchronizationActive(); return new DefaultTransactionStatus( transaction, newTransaction, actualNewSynchronization, definition.isReadOnly(), debug, suspendedResources); } //构造方法 public DefaultTransactionStatus( @Nullable Object transaction, boolean newTransaction, boolean newSynchronization, boolean readOnly, boolean debug, @Nullable Object suspendedResources) { this.transaction = transaction; this.newTransaction = newTransaction; this.newSynchronization = newSynchronization; this.readOnly = readOnly; this.debug = debug; this.suspendedResources = suspendedResources; }
3.开启事物
针对不同的事物管理器会有不同的事物开启过程,本例我们只看DataSourceTransactionManager下的事物开启过程:
protected void doBegin(Object transaction, TransactionDefinition definition) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; Connection con = null; try { // ConnectionHolder简介:包装JDBC连接的资源容器。DataSourceTransactionManager将该类的实例绑定到特定数据源的线程。 // 如果txObject没有ConnectionHolder或者connectionHolder并没有加同步锁,则为其设置ConnectionHolder并加同步锁 if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) { // 从数据源获取连接 Connection newCon = obtainDataSource().getConnection(); if (logger.isDebugEnabled()) { logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction"); } // 设置DataSourceTransactionObject的ConnectionHolder对象 txObject.setConnectionHolder(new ConnectionHolder(newCon), true); } // 设置同步锁标记 txObject.getConnectionHolder().setSynchronizedWithTransaction(true); // 从ConnectionHolder对象中获取连接 con = txObject.getConnectionHolder().getConnection(); // 设置连接的只读属性和数据库事物隔离级别 Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); // 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). // 如果需要,切换到手动提交。 // 在某些JDBC驱动程序中,这是非常昂贵的,所以我们不想做不必要的事情 // (例如,如果我们已经显式地配置了连接池来设置它)。 // 所以:如果连接设置了自动提交,这里要将其转换为手动提交 if (con.getAutoCommit()) { txObject.setMustRestoreAutoCommit(true); if (logger.isDebugEnabled()) { logger.debug("Switching JDBC Connection [" + con + "] to manual commit"); } con.setAutoCommit(false); } // 设置当前事物只读,如果定义了只读属性为true prepareTransactionalConnection(con, definition); // 设置当前事物为已激活 txObject.getConnectionHolder().setTransactionActive(true); // 设置超时时间(如果超时时间不等于默认超时时间) int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getConnectionHolder().setTimeoutInSeconds(timeout); } // Bind the connection holder to the thread. // 绑定ConnectionHolder到当前线程 if (txObject.isNewConnectionHolder()) { // 即TransactionSynchronizationManager类的resources对象: // 该对象保存每个事物线程对应的connection或session等类型的资源 // private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>("Transactional resources"); 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(前文没有讲解)对象,也已经在注释里做过介绍了。
4.初始化事物同步
/** * 根据需要初始化事务同步。 * Initialize transaction synchronization as appropriate. */ protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) { if (status.isNewSynchronization()) { // 设置事物激活状态 TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction()); // 设置事物隔离级别 TransactionSynchronizationManager.setCurrentTransactionIsolationLevel( definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ? definition.getIsolationLevel() : null); // 设置事物只读属性 TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly()); // 设置事物名称 TransactionSynchronizationManager.setCurrentTransactionName(definition.getName()); // 激活当前线程的事务同步。事务管理器在事务开始时调用。 TransactionSynchronizationManager.initSynchronization(); } }
总体来讲上面的内容还是比较简单的,不做过多的分析了。
5.其他事物特性处理
以上分析的都是基于单service下单个方法调用的事物创建过程,且当前不存在事物,那么对于其它的事物的特性呢?接下来就分析一下其他的特性,其实前面的章节已经有过简单的介绍了,这里再详细分析下。对于PROPAGATION_NESTED特性会直接抛出异常。
那么下面介绍一下PROPAGATION_SUPPORTS、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER特性事物处理过程,先来看一下代码片段:
// 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);
protected final DefaultTransactionStatus prepareTransactionStatus( TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction, boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) { DefaultTransactionStatus status = newTransactionStatus( definition, transaction, newTransaction, newSynchronization, debug, suspendedResources); prepareSynchronization(status, definition); return status; }
从代码里可以看到,该处理与创建真正的事物的过程相似,只是传递的参数不同罢了。大家可以多设定几种传播特性,跟踪一下代码即可