前言
多的不说可以到这里说明你有心连接spring对事物管理的底层源码,我先说一下我对这个类分析下来的理解,然后直接上源码我写的注释,不过你也知道,和这个类联系比较紧密的还有几个类,TransactionSynchronizationManager,还有选一个具体子类方便理解DataSourceTransactionManager,后面如果我有这个心,或者有人关注我,评论我我会在更一下,不然懒的在写出来了,费时间真的
我的理解
我看这个之前,首先想的是,什么是事物,对于DataSourceTransactionManager来说,就是Connection,取得一个connect开始执行sql,关掉自动提交,就是默认开启一个事物,如果需要新开一个事物,就是新开一个connect,那好了什么叫当前事物呢,在事物中我们线程用数据库连接,用的就是当前线程本地变量存放的connect,这个connect就是当前事物,有一种这个情况:我要在这个事物中新开一个事物,挂起这个事物,然后在开一个事物,对于线程来说,就是暂时把这个链接缓存起来,然后取一个新链接,来放到这个线程中,执行完,在换回来。没那么复杂。
因为我门定义一个线程只有一个线程变量保存connect,所以一个线程执行一个方法栈最多只可以在一个事物中,应为最多是一对一,所以我们可以通过线程取得当前事物。
所以我们开始事物,就是在threadlocal中放一个connect,
然后我们再来看看AbstractPlatformTransactionManager 这个类干什么,这个类就是做一下几件事
- 处理事务传递性
- 处理挂起事物,恢复事物时,同步更新线程变量TransactionSynchronizationManager
- 处理注册的回调方法,就是同一种类,放到一个list,然后在特定时间取出来for循环调用响应方法
定义了整个的开启事物,获取事物的骨架。给我提问,我会回复的
我注释的源码
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.transaction.support;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.Constants;
import org.springframework.transaction.IllegalTransactionStateException;
import org.springframework.transaction.InvalidTimeoutException;
import org.springframework.transaction.NestedTransactionNotSupportedException;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.TransactionSuspensionNotSupportedException;
import org.springframework.transaction.UnexpectedRollbackException;
/**
* Abstract base class that implements Spring's standard transaction workflow,
* serving as basis for concrete platform transaction managers like
* {@link org.springframework.transaction.jta.JtaTransactionManager}.
*
* <p>This base class provides the following workflow handling:
* <ul>
* <li>determines if there is an existing transaction;
* <li>applies the appropriate propagation behavior;
* <li>suspends and resumes transactions if necessary;
* <li>checks the rollback-only flag on commit;
* <li>applies the appropriate modification on rollback
* (actual rollback or setting rollback-only);
* <li>triggers registered synchronization callbacks
* (if transaction synchronization is active).
* </ul>
*
* <p>Subclasses have to implement specific template methods for specific
* states of a transaction, e.g.: begin, suspend, resume, commit, rollback.
* The most important of them are abstract and must be provided by a concrete
* implementation; for the rest, defaults are provided, so overriding is optional.
*
* <p>Transaction synchronization is a generic mechanism for registering callbacks
* that get invoked at transaction completion time. This is mainly used internally
* by the data access support classes for JDBC, Hibernate, JPA, etc when running
* within a JTA transaction: They register resources that are opened within the
* transaction for closing at transaction completion time, allowing e.g. for reuse
* of the same Hibernate Session within the transaction. The same mechanism can
* also be leveraged for custom synchronization needs in an application.
*
* <p>The state of this class is serializable, to allow for serializing the
* transaction strategy along with proxies that carry a transaction interceptor.
* It is up to subclasses if they wish to make their state to be serializable too.
* They should implement the {@code java.io.Serializable} marker interface in
* that case, and potentially a private {@code readObject()} method (according
* to Java serialization rules) if they need to restore any transient state.
*
* @author Juergen Hoeller
* @since 28.03.2003
* @see #setTransactionSynchronization
* @see TransactionSynchronizationManager
* @see org.springframework.transaction.jta.JtaTransactionManager
*/
@SuppressWarnings("serial")
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
/**
* Always activate transaction synchronization, even for "empty" transactions
* that result from PROPAGATION_SUPPORTS with no existing backend transaction.
* @see org.springframework.transaction.TransactionDefinition#PROPAGATION_SUPPORTS
* 自身不会开启事务,在事务范围内则使用相同事务,否则不使用事务
* @see org.springframework.transaction.TransactionDefinition#PROPAGATION_NOT_SUPPORTED
* 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
* @see org.springframework.transaction.TransactionDefinition#PROPAGATION_NEVER
* 以非事务方式执行,如果当前存在事务,则抛出异常
* 总是激活事务同步,甚至为“empty”的事务,由于没有现有后端事务的传播支持
*/
public static final int SYNCHRONIZATION_ALWAYS = 0;
/**
* Activate transaction synchronization only for actual transactions,
* that is, not for empty ones that result from PROPAGATION_SUPPORTS with
* no existing backend transaction.
* @see org.springframework.transaction.TransactionDefinition#PROPAGATION_REQUIRED
* 如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置
* @see org.springframework.transaction.TransactionDefinition#PROPAGATION_MANDATORY
* 支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
* @see org.springframework.transaction.TransactionDefinition#PROPAGATION_REQUIRES_NEW
* 创建新事务,无论当前存不存在事务,都创建新事务。
* 只为实际的事务 激活事务同步,不为空的,结果从没有现有后端事务的PROPAGATION_SUPPORTS.
*/
public static final int SYNCHRONIZATION_ON_ACTUAL_TRANSACTION = 1;
/**
* Never active transaction synchronization, not even for actual transactions.
* 永远不激活事务同步,即使实际的交易
*/
public static final int SYNCHRONIZATION_NEVER = 2;
/** Constants instance for AbstractPlatformTransactionManager */
private static final Constants constants = new Constants(AbstractPlatformTransactionManager.class);
protected transient Log logger = LogFactory.getLog(getClass());
private int transactionSynchronization = SYNCHRONIZATION_ALWAYS;
private int defaultTimeout = TransactionDefinition.TIMEOUT_DEFAULT;
private boolean nestedTransactionAllowed = false;
private boolean validateExistingTransaction = false;
private boolean globalRollbackOnParticipationFailure = true;
private boolean failEarlyOnGlobalRollbackOnly = false;
private boolean rollbackOnCommitFailure = false;
/**
* Set the transaction synchronization by the name of the corresponding constant
* in this class, e.g. "SYNCHRONIZATION_ALWAYS".
* @param constantName name of the constant
* @see #SYNCHRONIZATION_ALWAYS
*/
public final void setTransactionSynchronizationName(String constantName) {
setTransactionSynchronization(constants.asNumber(constantName).intValue());
}
/**
* Set when this transaction manager should activate the thread-bound
* transaction synchronization support. Default is "always".
* <p>Note that transaction synchronization isn't supported for
* multiple concurrent transactions by different transaction managers.
* Only one transaction manager is allowed to activate it at any time.
* @see #SYNCHRONIZATION_ALWAYS
* @see #SYNCHRONIZATION_ON_ACTUAL_TRANSACTION
* @see #SYNCHRONIZATION_NEVER
* @see TransactionSynchronizationManager
* @see TransactionSynchronization
*/
public final void setTransactionSynchronization(int transactionSynchronization) {
this.transactionSynchronization = transactionSynchronization;
}
/**
* Return if this transaction manager should activate the thread-bound
* transaction synchronization support.
*/
public final int getTransactionSynchronization() {
return this.transactionSynchronization;
}
/**
* Specify the default timeout that this transaction manager should apply
* if there is no timeout specified at the transaction level, in seconds.
* <p>Default is the underlying transaction infrastructure's default timeout,
* e.g. typically 30 seconds in case of a JTA provider, indicated by the
* {@code TransactionDefinition.TIMEOUT_DEFAULT} value.
* @see org.springframework.transaction.TransactionDefinition#TIMEOUT_DEFAULT
*/
public final void setDefaultTimeout(int defaultTimeout) {
if (defaultTimeout < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid default timeout", defaultTimeout);
}
this.defaultTimeout = defaultTimeout;
}
/**
* Return the default timeout that this transaction manager should apply
* if there is no timeout specified at the transaction level, in seconds.
* <p>Returns {@code TransactionDefinition.TIMEOUT_DEFAULT} to indicate
* the underlying transaction infrastructure's default timeout.
*/
public final int getDefaultTimeout() {
return this.defaultTimeout;
}
/**
* Set whether nested transactions are allowed. Default is "false".
* <p>Typically initialized with an appropriate default by the
* concrete transaction manager subclass.
*/
public final void setNestedTransactionAllowed(boolean nestedTransactionAllowed) {
this.nestedTransactionAllowed = nestedTransactionAllowed;
}
/**
* Return whether nested transactions are allowed.
*/
public final boolean isNestedTransactionAllowed() {
return this.nestedTransactionAllowed;
}
/**
* Set whether existing transactions should be validated before participating
* in them.
* <p>When participating in an existing transaction (e.g. with
* PROPAGATION_REQUIRES or PROPAGATION_SUPPORTS encountering an existing
* transaction), this outer transaction's characteristics will apply even
* to the inner transaction scope. Validation will detect incompatible
* isolation level and read-only settings on the inner transaction definition
* and reject participation accordingly through throwing a corresponding exception.
* <p>Default is "false", leniently ignoring inner transaction settings,
* simply overriding them with the outer transaction's characteristics.
* Switch this flag to "true" in order to enforce strict validation.
*/
public final void setValidateExistingTransaction(boolean validateExistingTransaction) {
this.validateExistingTransaction = validateExistingTransaction;
}
/**
* Return whether existing transactions should be validated before participating
* in them.
*/
public final boolean isValidateExistingTransaction() {
return this.validateExistingTransaction;
}
/**
* Set whether to globally mark an existing transaction as rollback-only
* after a participating transaction failed.
* <p>Default is "true": If a participating transaction (e.g. with
* PROPAGATION_REQUIRES or PROPAGATION_SUPPORTS encountering an existing
* transaction) fails, the transaction will be globally marked as rollback-only.
* The only possible outcome of such a transaction is a rollback: The
* transaction originator <i>cannot</i> make the transaction commit anymore.
* <p>Switch this to "false" to let the transaction originator make the rollback
* decision. If a participating transaction fails with an exception, the caller
* can still decide to continue with a different path within the transaction.
* However, note that this will only work as long as all participating resources
* are capable of continuing towards a transaction commit even after a data access
* failure: This is generally not the case for a Hibernate Session, for example;
* neither is it for a sequence of JDBC insert/update/delete operations.
* <p><b>Note:</b>This flag only applies to an explicit rollback attempt for a
* subtransaction, typically caused by an exception thrown by a data access operation
* (where TransactionInterceptor will trigger a {@code PlatformTransactionManager.rollback()}
* call according to a rollback rule). If the flag is off, the caller can handle the exception
* and decide on a rollback, independent of the rollback rules of the subtransaction.
* This flag does, however, <i>not</i> apply to explicit {@code setRollbackOnly}
* calls on a {@code TransactionStatus}, which will always cause an eventual
* global rollback (as it might not throw an exception after the rollback-only call).
* <p>The recommended solution for handling failure of a subtransaction
* is a "nested transaction", where the global transaction can be rolled
* back to a savepoint taken at the beginning of the subtransaction.
* PROPAGATION_NESTED provides exactly those semantics; however, it will
* only work when nested transaction support is available. This is the case
* with DataSourceTransactionManager, but not with JtaTransactionManager.
* @see #setNestedTransactionAllowed
* @see org.springframework.transaction.jta.JtaTransactionManager
*/
public final void setGlobalRollbackOnParticipationFailure(boolean globalRollbackOnParticipationFailure) {
this.globalRollbackOnParticipationFailure = globalRollbackOnParticipationFailure;
}
/**
* Return whether to globally mark an existing transaction as rollback-only
* after a participating transaction failed.
*/
public final boolean isGlobalRollbackOnParticipationFailure() {
return this.globalRollbackOnParticipationFailure;
}
/**
* Set whether to fail early in case of the transaction being globally marked
* as rollback-only.
* <p>Default is "false", only causing an UnexpectedRollbackException at the
* outermost transaction boundary. Switch this flag on to cause an
* UnexpectedRollbackException as early as the global rollback-only marker
* has been first detected, even from within an inner transaction boundary.
* <p>Note that, as of Spring 2.0, the fail-early behavior for global
* rollback-only markers has been unified: All transaction managers will by
* default only cause UnexpectedRollbackException at the outermost transaction
* boundary. This allows, for example, to continue unit tests even after an
* operation failed and the transaction will never be completed. All transaction
* managers will only fail earlier if this flag has explicitly been set to "true".
* @see org.springframework.transaction.UnexpectedRollbackException
*/
public final void setFailEarlyOnGlobalRollbackOnly(boolean failEarlyOnGlobalRollbackOnly) {
this.failEarlyOnGlobalRollbackOnly = failEarlyOnGlobalRollbackOnly;
}
/**
* Return whether to fail early in case of the transaction being globally marked
* as rollback-only.
*/
public final boolean isFailEarlyOnGlobalRollbackOnly() {
return this.failEarlyOnGlobalRollbackOnly;
}
/**
* Set whether {@code doRollback} should be performed on failure of the
* {@code doCommit} call. Typically not necessary and thus to be avoided,
* as it can potentially override the commit exception with a subsequent
* rollback exception.
* <p>Default is "false".
* @see #doCommit
* @see #doRollback
*/
public final void setRollbackOnCommitFailure(boolean rollbackOnCommitFailure) {
this.rollbackOnCommitFailure = rollbackOnCommitFailure;
}
/**
* Return whether {@code doRollback} should be performed on failure of the
* {@code doCommit} call.
*/
public final boolean isRollbackOnCommitFailure() {
return this.rollbackOnCommitFailure;
}
//---------------------------------------------------------------------
// Implementation of PlatformTransactionManager
//---------------------------------------------------------------------
/**
* This implementation handles propagation behavior. Delegates to
* {@code doGetTransaction}, {@code isExistingTransaction}
* and {@code doBegin}.
* @see #doGetTransaction
* @see #isExistingTransaction
* @see #doBegin
*/
@Override
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
//doGetTransaction()方法是抽象方法,具体的实现由具体的事务处理器提供
Object transaction = doGetTransaction();
// Cache debug flag to avoid repeated checks.
boolean debugEnabled = logger.isDebugEnabled();
//如果没有配置事务属性,则使用默认的事务属性
if (definition == null) {
//处理已存在的事务
definition = new DefaultTransactionDefinition();
}
//检查当前线程是否存在事务
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
//处理已存在的事务
return handleExistingTransaction(definition, transaction, debugEnabled