Spring技術內幕——事務的建立,掛起,迴歸,提交(事務攔截器和抽象事務管理器)
在涉及單個數據庫區域性事務的事務處理中,事務的最終實現和資料庫的支援是緊密相關的。對區域性資料庫事務來說,一個事務處理的操作單元往往對應著一系列的資料庫操作。
Spring事務處理主要分以下三個主要的過程:
(1)讀取和處理在Spring IoC容器中配置的事務處理屬性,並轉化為Spring事務處理所需要的內部資料結構。這裡涉及到的類是TransactionAttributeSourceAdvisor類。
(2)Spring的事務處理模組是通過AOP功能來實現宣告式事務處理的,通用的事務處理過程包括:處理事務配置屬性;事務配置屬性與執行緒繫結等。
TransactionProxyFactoryBean是Spring中管理事務的IoC容器,通過它生成Proxy物件,通過TransactionInterceptor來完成堆代理方法的攔截,正式這些AOP的攔截功能,將事務處理的功能編織進來。
(3)底層事務處理實現。Spring中底層事務處理的實現交由PlatformTransactionManager的具體實現類來實現,如DataSourceTransactionManager和HibernateTransactionManager等。
TransactionProxyFactoryBean解析(這只是實現事務的一種方法,其他類也能實現事務,例如DataSourceTransactionManager!!!)
TransactionInterceptor的呼叫時機,完成了Bean的依賴注入後:public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean implements BeanFactoryAware { private Pointcut pointcut; //通過Spring IoC容器依賴注入的PlatformTransactionManager事務管理器 public void setTransactionManager(PlatformTransactionManager transactionManager) { this.transactionInterceptor.setTransactionManager(transactionManager); } //通過依賴注入設定事務屬性,以Properties形式存放的事務屬性的key是方法名, //value是事務屬性描述,注入到TransactionInterceptor中 public void setTransactionAttributes(Properties transactionAttributes) { this.transactionInterceptor.setTransactionAttributes(transactionAttributes); } //通過依賴注入設定事務屬性源,通過事務屬性源可以找到需要使用的事務屬性 public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) { this.transactionInterceptor.setTransactionAttributeSource(transactionAttributeSource); } //通過依賴注入設定事務切入點,事務切入點根據觸發條件呼叫事務攔截器 public void setPointcut(Pointcut pointcut) { this.pointcut = pointcut; } //為事務攔截器設定管理事務的容器 public void setBeanFactory(BeanFactory beanFactory) { this.transactionInterceptor.setBeanFactory(beanFactory); } //建立Spring AOP事務處理的通知器Advisor protected Object createMainInterceptor() { //呼叫事務攔截器的方法,檢查必需的屬性是否設定 this.transactionInterceptor.afterPropertiesSet(); //如果在Spring配置中設定了事務切入點 if (this.pointcut != null) { //使用Spring預設的通知器封裝事務切入點和事務攔截器 return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor); } //如果在Spring配置中沒有設定事務切入點 else { //使用TransactionAttributeSourceAdvisor封裝預設的事務切入點 return new TransactionAttributeSourceAdvisor(this.transactionInterceptor); } } }
可以看到在AbstractSingletonProxyFactoryBean中的afterPropertiesSet方法中,呼叫了createMainInterceptor
//InitializingBean介面的實現方法,IoC容器初始化完成之後的回撥方法 public void afterPropertiesSet() { //事務的目標物件不能為空 if (this.target == null) { throw new IllegalArgumentException("Property 'target' is required"); } //事務目標物件必須是Bean引用,不能是Bean名稱 if (this.target instanceof String) { throw new IllegalArgumentException("'target' needs to be a bean reference, not a bean name as value"); } //如果代理類載入器為null,則使用預設的類載入器作用代理類載入器 if (this.proxyClassLoader == null) { this.proxyClassLoader = ClassUtils.getDefaultClassLoader(); } //建立代理工廠,Spring事務管理容器TransactionProxyFactoryBean通過//ProxyFactory完成AOP的基本功能,ProxyFactory提供事務代理物件,並將事務攔//截器設定為事務目標物件方法的攔截器 ProxyFactory proxyFactory = new ProxyFactory(); //如果在事務攔截器之前配置了額外的攔截器 if (this.preInterceptors != null) { //將這些事務之前的額外攔截器新增到通知器中 for (Object interceptor : this.preInterceptors) { proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor)); } } //加入Spring AOP事務處理通知器,createMainInterceptor()方法 //由子類TransactionProxyFactoryBean提供實現 proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor())); //如果在事務攔截器之後配置了額外攔截器 if (this.postInterceptors != null) { //將這些事務之後的額外攔截器新增到通知器中 for (Object interceptor : this.postInterceptors) { proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor)); } } //從當前容器中複製事務AOP相關配置到ProxyFactory中 proxyFactory.copyFrom(this); //建立AOP的目標源 TargetSource targetSource = createTargetSource(this.target); //為ProxyFactory設定AOP目標源 proxyFactory.setTargetSource(targetSource); //如果事務配置使用了代理介面 if (this.proxyInterfaces != null) { //為ProxyFactory設定代理介面 proxyFactory.setInterfaces(this.proxyInterfaces); } //如果事務代理不是直接應用於目標類或者介面 else if (!isProxyTargetClass()) { //將目標源的所有介面都設定為ProxyFactory的介面 proxyFactory.setInterfaces( ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), this.proxyClassLoader)); } //ProxyFactory物件根據給定的類載入器建立事務代理物件 //具體的建立過程我們在Spring的AOP原始碼分析中已經分析過,Spring根據是否 //實現介面而分別呼叫JDK動態代理或者CGLIB方式建立AOP代理物件 this.proxy = proxyFactory.getProxy(this.proxyClassLoader); }
事務攔截器TransactionInterceptor的實現
管理Spring事務的IoC容器TransactionProxyFactoryBean已經完成了事務配置的讀取,設定好了事務攔截器和切入點。當應用呼叫被配置事務的方法時,首先通過getObject方法向Spring事務管理容器索取被被管理方法的事務屬性,觸發呼叫事務攔截器的攔截方法進行事務處理。
在對Spring AOP原始碼分析中關於AOP代理如何起作用時,我們知道Spring的AOP代理通過invoke回撥方法對切入點方法進行攔截處理,這個invoke方法是AOP聯盟的方法攔截器MethodInterceptor介面中定義的方法,用於對AOP代理物件的方法進行包裝處理。事務攔截器TransactionInterceptor正是通過這個invoke攔截方法實現事務的攔截處理,原始碼如下:
//事務攔截器的攔截方法
public Object invoke(final MethodInvocation invocation) throws Throwable {
//通過AOP獲取事務的目標類
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
//通過事務屬性源TransactionAttributeSource讀取事務的屬性配置,即呼叫上面名稱匹配
//事務屬性源NameMatchTransactionAttributeSource的方法
final TransactionAttribute txAttr =
getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);
//獲取Spring事務管理IoC容器配置的事務處理器
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
//獲取目標類指定方法的事務連線點
final String joinpointIdentification = methodIdentification(invocation.getMethod(), targetClass);
//區分不同型別的PlatformTransactionManager事務處理器,不同型別的事務處理器呼叫//方式不同。對CallbackPreferringPlatformTransactionManager,需要回調函式來//實現事務的建立和提交,對非CallbackPreferringPlatformTransactionManager來//說,則不需要使用回撥函式來實現事務處理。
//非CallbackPreferringPlatformTransactionManager型別的事務處理器
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
//建立事務,將當前事務狀態和資訊儲存到TransactionInfo物件中
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
//沿著攔截器鏈呼叫處理,使得最後目標物件的方法得到呼叫
retVal = invocation.proceed();
}
catch (Throwable ex) {
//在呼叫攔截器攔過程中出現異常,則根據事務配置進行提交或回滾處理
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
//清除與當前執行緒繫結的事務資訊
finally {
cleanupTransactionInfo(txInfo);
}
//通過事務處理器來對事務進行提交
commitTransactionAfterReturning(txInfo);
return retVal;
}
//CallbackPreferringPlatformTransactionManager型別的事務處理器
else {
//通過回撥函式對事務進行處理
try {
//執行實現TransactionCallback介面的doInTransaction回撥方法
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
new TransactionCallback<Object>() {
//實現TransactionCallback介面匿名內部類的回撥方法
public Object doInTransaction(TransactionStatus status) {
//建立和準備事務
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
try {
//沿著攔截器攔呼叫
return invocation.proceed();
}
//攔截器鏈處理過程中產生異常
catch (Throwable ex) {
//如果事務對異常進行回滾處理
if (txAttr.rollbackOn(ex)) {
//如果異常時執行時異常,則事務回滾處理
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
//如果不是執行時異常,則提交處理
else {
throw new ThrowableHolderException(ex);
}
}
//如果事務對異常不進行回滾處理
else {
//提交處理
return new ThrowableHolder(ex);
}
}
//清除當前執行緒繫結的事務資訊
finally {
cleanupTransactionInfo(txInfo);
}
}
});
//對呼叫結果異常進行處理。
//如果是ThrowableHolder型別的異常,則轉換為Throwable丟擲
if (result instanceof ThrowableHolder) {
throw ((ThrowableHolder) result).getThrowable();
}
//如果不是ThrowableHolder型別的異常,則異常不做處理直接丟擲
else {
return result;
}
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
}
}
事務建立(建立的結果是生成一個TransactionInfo物件)
事務攔截器TransactionInterceptor回撥方法invoke通過呼叫TransactionAspectSupport事務切面支援類中的createTransactionIfNecessary和prepareTransactionInfo方法建立事務物件:
//根據給定的事務屬性建立事務物件
protected TransactionInfo createTransactionIfNecessary(
PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {
//讀取事務方法呼叫的事務配置屬性
if (txAttr != null && txAttr.getName() == null) {
//如果事務名稱為null,則使用方法的名稱(事務連線點標識)作為事務名稱,
//呼叫一個實現DelegatingTransactionAttribute介面的匿名內部類
txAttr = new DelegatingTransactionAttribute(txAttr) {
//使用方法名稱作為事務名稱
public String getName() {
return joinpointIdentification;
}
};
}
//事務狀態封裝了事務執行的狀態資訊
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
//事務處理器建立事務,並且返回當前事務的狀態資訊
status = tm.getTransaction(txAttr);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
"] because no transaction manager has been configured");
}
}
}
//準備事務資訊,事務資訊TransactionInfo封裝了事務配置和狀態資訊
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
//準備事務資訊
protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm,
TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) {
//建立事務資訊物件
TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
//如果事務屬性不為null,需要為方法使用事務
if (txAttr != null) {
if (logger.isTraceEnabled()) {
logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
}
//為事務資訊物件設定事務狀態
txInfo.newTransactionStatus(status);
}
//如果事務屬性為null,不需要為方法使用事務
else {
if (logger.isTraceEnabled())
logger.trace("Don't need to create transaction for [" + joinpointIdentification +
"]: This method isn't transactional.");
}
//把當前建立的事務資訊物件和執行緒繫結
txInfo.bindToThread();
return txInfo;
}
通過上面對TransactionAspectSupport事務切面支援類建立事務資訊物件的原始碼分析,我們瞭解了在建立事務資訊物件過程中建立事務狀態,將建立的事務資訊物件和當前執行緒資源繫結等基本的處理流程。在建立事務資訊物件的方法中,事務處理器的tm.getTransaction(txAttr);是真正底層建立事務物件的方法,下面我們繼續分析事務處理器建立事務物件的過程。
抽象事務管理器AbstractPlatformTransactionManager獲取事務:
抽象事務管理器AbstractPlatformTransactionManager提供了建立事務的模板,這個模板會被具體的事務處理器所使用,抽象事務管理器根據事務屬性配置和當前執行緒繫結資訊對事務是否需要建立以及如何建立進行一些通用的處理,然後把事務建立的底層細節交給具體的事務處理器實現。抽象事務管理器建立事務的模板方法如下:
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
//doGetTransaction()方法是抽象方法,具體的實現由具體的事務處理器提供
Object transaction = doGetTransaction();
boolean debugEnabled = logger.isDebugEnabled();
//如果沒有配置事務屬性,則使用預設的事務屬性
if (definition == null) {
definition = new DefaultTransactionDefinition();
}
//檢查當前執行緒是否存在事務,如果已存在事務,那麼需要根據在事務屬性中定義的事務傳播屬性來處理事務的產生
if (isExistingTransaction(transaction)) {
//處理已存在的事務的情況
return handleExistingTransaction(definition, transaction, debugEnabled);
}
//檢查事務屬性中timeout超時屬性設定是否合理
if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
}
//對事務屬性中配置的事務傳播特性處理
//如果事務傳播特性配置的是mandatory,當前沒有事務存在,丟擲異常
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
//如果事務傳播特性為required、required_new或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);
//建立事務的呼叫,具體實現由具體的事務處理器提供
doBegin(transaction, definition);
//初始化和同步事務狀態
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException ex) {
resume(null, suspendedResources);
throw ex;
}
catch (Error err) {
resume(null, suspendedResources);
throw err;
}
}
else {
//建立空事務,針對supported型別的事務傳播特性,啟用和當前執行緒繫結的事務
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
//準備事務狀態
return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
}
}
//準備事務狀態
protected final DefaultTransactionStatus prepareTransactionStatus(
TransactionDefinition definition, Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, Object suspendedResources) {
//建立事務狀態
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, newTransaction, newSynchronization, debug, suspendedResources);
//準備事務狀態
prepareSynchronization(status, definition);
return status;
}
//建立事務狀態
protected DefaultTransactionStatus newTransactionStatus(
TransactionDefinition definition, Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, Object suspendedResources) {
//判斷是否是新事務,如果是新事務,則需要把事務屬性存放到當前執行緒中
boolean actualNewSynchronization = newSynchronization &&
!TransactionSynchronizationManager.isSynchronizationActive();
return new DefaultTransactionStatus(
transaction, newTransaction, actualNewSynchronization,
definition.isReadOnly(), debug, suspendedResources);
}
//初始化事務屬性
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();
}
}
抽象事務管理器AbstractPlatformTransactionManager處理已存在的事務:
對於新事務的處理相對比較簡單,只需根據事務屬性配置建立,同時將事務隔離級別等屬性儲存到事務繫結的執行緒資源中。而對於已存在的事務處理相對比較複雜一些,在抽象事務管理器AbstractPlatformTransactionManager中通過handleExistingTransaction方法來處理已存在的事務:
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
//如果事務傳播特性為:never,則丟擲異常
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
//如果事務傳播特性是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);
}
//如果事務傳播特性是required_new,則建立新事務,同時把當前執行緒中存在的
//事務掛起
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
}
//掛起已存在的事務
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
//將掛起的事務狀態儲存起來
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
//建立新事務
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
catch (Error beginErr) {
resumeAfterBeginException(transaction, suspendedResources, beginErr);
throw beginErr;
}
}
//如果事務傳播特性是nested巢狀事務
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() + "]");
}
//如果允許使用savepoint儲存點儲存巢狀事務
if (useSavepointForNestedTransaction()) {
//為當前事務建立一個儲存點
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
}
//如果不允許使用savepoint儲存點儲存巢狀事務
else {
//使用JTA的巢狀commit/rollback呼叫
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, null);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
}
//對於事務傳播特性為supported和required的處理
if (debugEnabled) {
logger.debug("Participating in existing transaction");
}
//校驗已存在的事務,如果已有事務與事務屬性配置不一致,則丟擲異常
if (isValidateExistingTransaction()) {
//如果事務隔離級別不是預設隔離級別
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
//獲取當前事務的隔離級別
Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
//如果獲取到的當前事務隔離級別為null獲取不等於事務屬性配置的隔離級別
if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
Constants isoConstants = DefaultTransactionDefinition.constants;
throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] specifies isolation level which is incompatible with existing transaction: " + (currentIsolationLevel != null ? isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) : "(unknown)"));
}
}
//如果事務不是隻讀
if (!definition.isReadOnly()) {
//如果當前已有事務是隻讀
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] is not marked as read-only but existing transaction is");
}
}
}
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
//返回當前事務的執行狀態
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
事務的掛起:
如果當前執行緒存在事務,但事務傳播特性又要求開啟新事務時,需要將已有的事務進行掛起,事務的掛起涉及執行緒與事務資訊的儲存,實現原始碼如下:
protected final SuspendedResourcesHolder suspend(Object transaction) throws TransactionException {
//如果事務是啟用的,且當前執行緒事務同步機制也是啟用狀態
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 ex) {
doResumeSynchronization(suspendedSynchronizations);
throw ex;
}
catch (Error err) {
doResumeSynchronization(suspendedSynchronizations);
throw err;
}
}
//如果事務是啟用的,但是事務同步機制不是啟用的,則只需要儲存事務狀態,不
//需要重置事務相關的執行緒區域性變數
else if (transaction != null) {
Object suspendedResources = doSuspend(transaction);
return new SuspendedResourcesHolder(suspendedResources);
}
//事務和事務同步機制都不是啟用的,則不要想處理
else {
return null;
}
}
事務的掛起:
如果當前執行緒存在事務,但事務傳播特性又要求開啟新事務時,需要將已有的事務進行掛起,事務的掛起涉及執行緒與事務資訊的儲存,實現原始碼如下:
protected final SuspendedResourcesHolder suspend(Object transaction) throws TransactionException {
//如果事務是啟用的,且當前執行緒事務同步機制也是啟用狀態
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 ex) {
doResumeSynchronization(suspendedSynchronizations);
throw ex;
}
catch (Error err) {
doResumeSynchronization(suspendedSynchronizations);
throw err;
}
}
//如果事務是啟用的,但是事務同步機制不是啟用的,則只需要儲存事務狀態,不
//需要重置事務相關的執行緒區域性變數
else if (transaction != null) {
Object suspendedResources = doSuspend(transaction);
return new SuspendedResourcesHolder(suspendedResources);
}
//事務和事務同步機制都不是啟用的,則不要想處理
else {
return null;
}
}
事務的提交:
當事務方法處理成功之後,需要將當前事務提交,將更改同步到資料庫中,事務提交的入口呼叫在TransactionInterceptor的invoke方法事中時間,提交的實現原始碼如下:
public final void commit(TransactionStatus status) throws TransactionException {
//如果事務的執行狀態已經結束,則丟擲異常
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
//如果事務執行狀態時回滾
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Transactional code has requested rollback");
}
//處理事務回滾
processRollback(defStatus);
return;
}
//如果事務沒有被標記為回滾時提交,且事務狀態時全域性回滾
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
}
//回滾處理
processRollback(defStatus);
//如果事務狀態時新事務,或者在全域性回滾時失敗
if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
throw new UnexpectedRollbackException(
"Transaction rolled back because it has been marked as rollback-only");
}
return;
}
//處理提交
processCommit(defStatus);
}
//提交處理操作
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
//事務提交的準備工作,有具體的事務處理器完成
prepareForCommit(status);
triggerBeforeCommit(status);
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
boolean globalRollbackOnly = false;
//如果事務狀態是新事務,或者全域性回滾失敗
if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
//設定事務全域性回滾
globalRollbackOnly = status.isGlobalRollbackOnly();
}
//巢狀事務處理
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Releasing transaction savepoint");
}
//釋放掛起事務儲存點
status.releaseHeldSavepoint();
}
//如果當前事務是新事務
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction commit");
}
//呼叫具體事務處理器提交事務
doCommit(status);
}
//如果事務被標記為全域性回滾
if (globalRollbackOnly) {
throw new UnexpectedRollbackException(
"Transaction silently rolled back because it has been marked as rollback-only");
}
}
//提交過程中產生未預期的回滾異常,則回滾處理
catch (UnexpectedRollbackException ex) {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
throw ex;
}
//對提交過程中產生的事務異常處理
catch (TransactionException ex) {
//如果回滾失敗,則進行回滾異常處理
if (isRollbackOnCommitFailure()) {
doRollbackOnCommitException(status, ex);
}
else {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
}
throw ex;
}
//對提交過程中產生的異常處理
catch (RuntimeException ex) {
//如果不是在完成前呼叫的
if (!beforeCompletionInvoked) {
//觸發完成前的回撥方法
triggerBeforeCompletion(status);
}
//進行回滾異常處理
doRollbackOnCommitException(status, ex);
throw ex;
}
//對提交過程中產生的錯誤處理
catch (Error err) {
if (!beforeCompletionInvoked) {
triggerBeforeCompletion(status);
}
doRollbackOnCommitException(status, err);
throw err;
}
//觸發提交之後的回撥操作
try {
triggerAfterCommit(status);
}
finally {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
}
}
//提交完成之後清除事務相關狀態
finally {
cleanupAfterCompletion(status);
}
}
事務的回滾:當在事務處理過程中產生異常,或者提交失敗時,往往需要對資料庫中已有的更改做回滾操作,即恢復到操作之前的狀態,回滾的實現程式碼如下:
public final void rollback(TransactionStatus status) throws TransactionException {
//如果事務狀態已完成,則丟擲異常
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
//處理回滾的操作
processRollback(defStatus);
}
//回滾操作
private void processRollback(DefaultTransactionStatus status) {
try {
try {
//觸發完成前的回撥操作
triggerBeforeCompletion(status);
//巢狀事務回滾處理
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 if (status.hasTransaction()) {
//如果當前事務狀態為本地回滾,或全域性回滾失敗
if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
if (status.isDebug()) {
logger.debug(
"Participating transaction failed - marking existing transaction as rollback-only");
}
//設定當前事務狀態為回滾
doSetRollbackOnly(status);
}
//當前事務狀態沒有設定為本地回滾,且沒有產生全域性回滾失敗,則
//由執行緒中的前一個事務來處理回滾,這個步驟任何處理
else {
if (status.isDebug()) {
logger.debug(
"Participating transaction failed - letting transaction originator decide on rollback");
}
}
}
//如果當前執行緒沒有事務
else {
logger.debug("Should roll back transaction but cannot - no transaction available");
}
}
//對回滾操作過程中的執行時異常和錯誤的處理
catch (RuntimeException ex) {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw ex;
}
catch (Error err) {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw err;
}
//回滾操作完成後,觸發回滾之後回撥操作
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
}
//清除回滾之後事務狀態資訊
finally {
cleanupAfterCompletion(status);
}
}