Spring事務抽象的是事務管理和事務策略。而實現則由各種資源方實現的。我們最常用的數據庫實現:DataSourceTransactionManager
嘗試閱讀一下spring 的實現代碼,由3個核心類:
1,PlatformTransactionManager
public interface PlatformTransactionManager { TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException;
事務管理的抽象,一個獲取事務狀態,一個提交事務,一個回滾事務。
2,TransactionStatus
public interface TransactionStatus extends SavepointManager, Flushable { boolean isNewTransaction(); boolean hasSavepoint(); void setRollbackOnly(); boolean isRollbackOnly(); void flush(); boolean isCompleted(); }
事務狀態的抽象
3,DefaultTransactionDefinition
public interface TransactionDefinition { int getPropagationBehavior(); int getIsolationLevel(); int getTimeout(); boolean isReadOnly(); String getName(); }
事務策略抽象,1,事務傳播行為,2,事務隔離級別,3,超時時間,4,只讀屬性
編程的方法實現事務管理使用簡單代碼:
transactionTemplate.execute(new TransactionCallback<String>() { @Override public String doInTransaction(TransactionStatus status) { updatePayPrice(orderData, offer); return null; } });
類似下面的配置:
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate" p:transactionManager-ref="txManager" scope="prototype" />
TransactionTemplate繼承了DefaultTransactionDefinition也就是TransactionDefinition默認實現,afterPropertiesSet方法檢查transactionManager,
核心方法execute,其中四步:0.獲取一個事務狀態,1,執行業務邏輯 2,出現異常,3,沒有異常事務提交
public class TransactionTemplate extends DefaultTransactionDefinition implements TransactionOperations, InitializingBean { /** Logger available to subclasses */ protected final Log logger = LogFactory.getLog(getClass()); private PlatformTransactionManager transactionManager; public TransactionTemplate() { } public TransactionTemplate(PlatformTransactionManager transactionManager) { this.transactionManager = transactionManager; } public TransactionTemplate(PlatformTransactionManager transactionManager, TransactionDefinition transactionDefinition) { super(transactionDefinition); this.transactionManager = transactionManager; } public void setTransactionManager(PlatformTransactionManager transactionManager) { this.transactionManager = transactionManager; } /** * Return the transaction management strategy to be used. */ public PlatformTransactionManager getTransactionManager() { return this.transactionManager; } @Override public void afterPropertiesSet() { if (this.transactionManager == null) { throw new IllegalArgumentException("Property 'transactionManager' is required"); } } @Override public <T> T execute(TransactionCallback<T> action) throws TransactionException { if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) { return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action); } else { // 0.獲取一個事務狀態 TransactionStatus status = this.transactionManager.getTransaction(this); T result; try { //1.執行業務邏輯 result = action.doInTransaction(status); } // 2.異常則回退 catch (RuntimeException ex) { // Transactional code threw application exception -> rollback rollbackOnException(status, ex); throw ex; } catch (Error err) { // Transactional code threw error -> rollback rollbackOnException(status, err); throw err; } catch (Exception ex) { // Transactional code threw unexpected exception -> rollback rollbackOnException(status, ex); throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception"); } // 3.沒有異常事務提交 this.transactionManager.commit(status); return result; } } private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException { logger.debug("Initiating transaction rollback on application exception", ex); try { this.transactionManager.rollback(status); } catch (TransactionSystemException ex2) { logger.error("Application exception overridden by rollback exception", ex); ex2.initApplicationException(ex); throw ex2; } catch (RuntimeException ex2) { logger.error("Application exception overridden by rollback exception", ex); throw ex2; } catch (Error err) { logger.error("Application exception overridden by rollback error", ex); throw err; } } }
0,獲取一個事務狀態
this.transactionManager.getTransaction(this);
這里的transactionManager就是前面使用代碼的配置中txManager,就是DataSourceTransactionManager,模版類AbstractPlatformTransactionManager。而傳參this就是DefaultTransactionDefinition。
下面是AbstractPlatformTransactionManager里的模版方法:
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { // 進來就先獲取事務 Object transaction = doGetTransaction(); // Cache debug flag to avoid repeated checks. // 這里為打日志判斷日志級別做的優化,這個在http://www.cnblogs.com/killbug/p/6721047.html 最后有解釋。 boolean debugEnabled = logger.isDebugEnabled(); if (definition == null) { // Use defaults if no transaction definition given. definition = new DefaultTransactionDefinition(); } if (isExistingTransaction(transaction)) { // Existing transaction found -> check propagation behavior to find out how to behave. return handleExistingTransaction(definition, transaction, debugEnabled); } // Check definition settings for new transaction. if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout()); } // No existing transaction found -> check propagation behavior to find out how to proceed. // 配置了PROPAGATION_MANDATORY就不能調用這個方法的,這個方法是開始獲取事務的地方 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'"); } 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 { // 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); } }
1,回滾代碼:
private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException { logger.debug("Initiating transaction rollback on application exception", ex); try { this.transactionManager.rollback(status); } catch (TransactionSystemException ex2) { logger.error("Application exception overridden by rollback exception", ex); ex2.initApplicationException(ex); throw ex2; } catch (RuntimeException ex2) { logger.error("Application exception overridden by rollback exception", ex); throw ex2; } catch (Error err) { logger.error("Application exception overridden by rollback error", ex); throw err; } }
transactionManager.rollback
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); } }
事務提交:
// 模版 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); // Throw UnexpectedRollbackException only at outermost transaction boundary // or if explicitly asked to. if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) { throw new UnexpectedRollbackException( "Transaction rolled back because it has been marked as rollback-only"); } return; } processCommit(defStatus); }
AbstractPlatformTransactionManager做為模版類,代碼清晰。
我們發現在上面的execute,異常會退時是不沒有任何區分什么異常會滾,什么異常不會滾,都是走rollbackOnException。其實我們只要在業務方法中把異常吃掉即可,另外對於回滾后異常拋出,在最外層再把異常做處理。
本篇沒有真正深入了解原理實現,寫在這里是為了開個頭。