1.引
通過(guò)前面的分析,已經(jīng)成功的創(chuàng)建了事物,但是不要忘了,當(dāng)前方法仍在方法攔截器鏈中?;仡櫼幌麓a片段:
// 2.處理聲明式事物
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
// 2.2 創(chuàng)建事物
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
System.out.println("==創(chuàng)建了名為:["+joinpointIdentification+"]的事物");
Object retVal = null;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
// 2.3 繼續(xù)調(diào)用方法攔截器鏈,這里一般將會(huì)調(diào)用目標(biāo)類的方法,如:com.lyc.cn.v2.day09.AccountServiceImpl.save方法
retVal = invocation.proceedWithInvocation();
} catch (Throwable ex) {
// target invocation exception
// 2.4 如果目標(biāo)類方法拋出異常,則在此處理,例如:事物回滾
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
} finally {
// 2.5 清除上一步創(chuàng)建的事物信息
cleanupTransactionInfo(txInfo);
}
// 2.6 調(diào)用成功完成后執(zhí)行,但不是在異常被處理后執(zhí)行。如果我們不創(chuàng)建事務(wù),就什么也不做。
commitTransactionAfterReturning(txInfo);
return retVal;
}
關(guān)于攔截器鏈的調(diào)用、目標(biāo)方法的調(diào)用等不做過(guò)多的分析了,前面都有介紹。
那么接下來(lái)的處理也會(huì)分為兩種情況,有異常和無(wú)異常兩種情況,有異常的話,那么可能會(huì)執(zhí)行回滾等操作;沒(méi)有異常的話,可能會(huì)執(zhí)行事物提交等操作,接下來(lái)對(duì)兩種情況逐個(gè)分析。
2.業(yè)務(wù)方法發(fā)生異常之后的處理
/**
* 處理異常以完成事物,基于配置該事物可能回滾也可能提交
* Handle a throwable, completing the transaction.
* We may commit or roll back, depending on the configuration.
* @param txInfo information about the current transaction
* @param ex throwable encountered
*/
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "] after exception: " + ex);
}
// 1.回滾
/**
* txInfo.transactionAttribute.rollbackOn(ex)判斷回滾的條件:
*
* 1. 如果自定了RollbackRuleAttribute列表,如果當(dāng)前異常匹配到了RollbackRuleAttribute其中的條目,則回滾
* 例如:可以通過(guò)rollbackFor指定觸發(fā)回滾的異常@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
*
* 2. 否則如果異常是RuntimeException或者Error的類型,則回滾
*
* 3. 其他的異常是不會(huì)回滾的,這里要注意一下...
*/
if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
try {
// 執(zhí)行回滾
System.out.println("==準(zhǔn)備回滾"+txInfo.getJoinpointIdentification());
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
} catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
ex2.initApplicationException(ex);
throw ex2;
} catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by rollback exception", ex);
throw ex2;
}
}
// 2.如果未能滿足回滾條件,則有可能會(huì)提交事物,也有可能會(huì)回滾事物
// 注意:如果TransactionStatus.isRollbackOnly()為true,則仍然會(huì)執(zhí)行回滾
else {
// We don't roll back on this exception.
// Will still roll back if TransactionStatus.isRollbackOnly() is true.
try {
System.out.println("==準(zhǔn)備提交"+txInfo.getJoinpointIdentification());
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
} catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by commit exception", ex);
ex2.initApplicationException(ex);
throw ex2;
} catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by commit exception", ex);
throw ex2;
}
}
}
}
2.1 判斷回滾條件:
- 如果自定了RollbackRuleAttribute列表,如果當(dāng)前異常匹配到了RollbackRuleAttribute其中的條目,則回滾
例如:可以通過(guò)rollbackFor指定觸發(fā)回滾的異常@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)。 - 否則如果異常是RuntimeException或者Error的類型,則回滾。
- 其他的異常是不會(huì)回滾的。
2.2 正?;貪L
如果滿足了if條件,那么當(dāng)前事物會(huì)執(zhí)行回滾操作
2.3 回滾或提交
如果未能滿足if條件,那么當(dāng)前事物可能會(huì)被提交、可能會(huì)被回滾。例如當(dāng)前事物的rollbackOnly為true,依然會(huì)執(zhí)行回滾操作。當(dāng)然如果未能滿足回滾條件的話,即使該事物拋出異常,依然會(huì)被提交。
接下來(lái)對(duì)正?;貪L、回滾或提交逐個(gè)分析。
3.正?;貪L
// 執(zhí)行回滾前檢查事物狀態(tài)
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, false);
}
// 執(zhí)行回滾
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
try {
boolean unexpectedRollback = unexpected;
try {
// 1.事物完成之前的觸發(fā)器調(diào)用
triggerBeforeCompletion(status);
// 2.如果有保存點(diǎn),則調(diào)用rollbackToHeldSavepoint回滾到保存點(diǎn)
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Rolling back transaction to savepoint");
}
status.rollbackToHeldSavepoint();
}
// 3.如果當(dāng)前事物是一個(gè)新的事物,則調(diào)用doRollback執(zhí)行給定事物的回滾
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction rollback");
}
doRollback(status);
}
else {
// Participating in larger transaction
// 4.如果當(dāng)前事物并非獨(dú)立事物,則將當(dāng)前事物的rollbackOnly屬性標(biāo)記為true,等到事物鏈完成之后,一起執(zhí)行回滾
// 如果當(dāng)前存在事物,但是
// 事物的rollbackOnly屬性已經(jīng)被標(biāo)記為true
// 或者globalRollbackOnParticipationFailure(返回是否僅在參與事務(wù)失敗后才將現(xiàn)有事務(wù)全局標(biāo)記為回滾)為true
if (status.hasTransaction()) {
if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
if (status.isDebug()) {
logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
}
System.out.println("==當(dāng)前事物并非獨(dú)立事物,且RollbackOnly為true\n");
// 則將ConnectionHolder中的rollbackOnly標(biāo)記為true
doSetRollbackOnly(status);
}
else {
if (status.isDebug()) {
logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
}
}
}
// 如果當(dāng)前不存在事物,則不會(huì)回滾
// 例如配置了 @Transactional(propagation = Propagation.NOT_SUPPORTED)
else {
logger.debug("Should roll back transaction but cannot - no transaction available");
}
// Unexpected rollback only matters here if we're asked to fail early
if (!isFailEarlyOnGlobalRollbackOnly()) {
unexpectedRollback = false;
}
}
}
catch (RuntimeException | Error ex) {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw ex;
}
// 5.事物完成之后的觸發(fā)器調(diào)用
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
// Raise UnexpectedRollbackException if we had a global rollback-only marker
if (unexpectedRollback) {
throw new UnexpectedRollbackException("Transaction rolled back because it has been marked as rollback-only");
}
}
finally {
cleanupAfterCompletion(status);
}
}
- 事物完成前、完成后觸發(fā)器的調(diào)用,例如:如果我們?cè)跇I(yè)務(wù)方法里注冊(cè)了TransactionSynchronizationAdapter,那么在這里會(huì)分別執(zhí)行其beforeCompletion、afterCompletion,以完成一些額外的功能擴(kuò)展。關(guān)于TransactionSynchronizationAdapter我們留在后面講解,這里大家只需要了解會(huì)在事物完成前后調(diào)用一些額外的方法即可。
- 如果有保存點(diǎn),則調(diào)用rollbackToHeldSavepoint回滾到保存點(diǎn)
- 如果當(dāng)前事物是一個(gè)新的事物,則調(diào)用doRollback執(zhí)行給定事物的回滾
- 如果當(dāng)前事物并非獨(dú)立事物,則將當(dāng)前事物的rollbackOnly屬性標(biāo)記為true,等到事物鏈完成之后,一起執(zhí)行回滾
大概的流程就是這樣了,因?yàn)槲覀兎治龅氖菃蝧ervice下的單個(gè)業(yè)務(wù)方法調(diào)用,所以這里我們還是只分析最簡(jiǎn)單的doRollback正?;貪L調(diào)用(事物嵌套留在后面講解)
關(guān)于doRollback的調(diào)用,對(duì)于不同的事物管理器分別有不同的調(diào)用方法,這里我們只看DataSourceTransactionManager的回滾方法:
@Override
protected void doRollback(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
}
try {
con.rollback();
}
catch (SQLException ex) {
throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
}
}
該方法很簡(jiǎn)單,從ConnectionHolder中拿到連接,執(zhí)行回滾。這里涉及到具體的JDBC驅(qū)動(dòng)的方法調(diào)用,感興趣的同學(xué)可以自己深入分析下,就不多做介紹了。
4.回滾或提交
public final void commit(TransactionStatus status) throws TransactionException {
// 如果當(dāng)前事物已經(jīng)被標(biāo)記為完成,拋出異常
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;
// 如果rollbackOnly為true,則回滾
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Transactional code has requested rollback");
}
processRollback(defStatus, false);
return;
}
// shouldCommitOnGlobalRollbackOnly --> 返回是否對(duì)標(biāo)記為僅以全局方式回滾的事務(wù)調(diào)用
// defStatus.isGlobalRollbackOnly() --> 實(shí)現(xiàn)了SmartTransactionObject并且事物的rollbackOnly被標(biāo)記為true
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);
}
關(guān)于回滾和提交的判斷條件注釋都寫(xiě)的很清晰了,對(duì)于rollbackOnly這里不做太多的介紹,留在后面的章節(jié)分析。大家只要記住,事物到了這里,可能會(huì)回滾也可能會(huì)提交即可。