javascript
Spring Boot Transaction 源码解析(二)
目錄
DataSourceTransactionManager
doGetTransaction
?isExistingTransaction
doBegin?
?doCommit
doSuspend
doRollback
doCleanupAfterCompletion
DataSourceUtils
ConnectionSynchronization
?suspend
JDBC事務(wù)時(shí)Spring 事務(wù)的具體實(shí)現(xiàn)。
DataSourceTransactionManager
public class DataSourceTransactionManager extends AbstractPlatformTransactionManagerimplements ResourceTransactionManager, InitializingBean {//數(shù)據(jù)庫(kù)DataSourceprivate DataSource dataSource;private boolean enforceReadOnly = false; }doGetTransaction
構(gòu)造DataSourceTransactionObject,存儲(chǔ)ConnectionHolder 。
@Overrideprotected Object doGetTransaction() {DataSourceTransactionObject txObject = new DataSourceTransactionObject();txObject.setSavepointAllowed(isNestedTransactionAllowed()); //通過(guò)DataSource獲取ConnectionHolder ConnectionHolder conHolder =(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource()); //DataSourceTransactionObject設(shè)置ConnectionHolder txObject.setConnectionHolder(conHolder, false);return txObject;}?isExistingTransaction
如果存在getConnectionHolder,并且有活躍事務(wù),則表示已存在事務(wù)。
@Overrideprotected boolean isExistingTransaction(Object transaction) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());}doBegin?
主要功能就是保存Connection,設(shè)置事務(wù)狀態(tài)。
@Overrideprotected void doBegin(Object transaction, TransactionDefinition definition) {//獲取事務(wù)對(duì)象。DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;Connection con = null;try {//如果沒(méi)有ConnectionHolder,則構(gòu)造一個(gè)。if (!txObject.hasConnectionHolder() ||txObject.getConnectionHolder().isSynchronizedWithTransaction()) {Connection newCon = obtainDataSource().getConnection();if (logger.isDebugEnabled()) {logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");}txObject.setConnectionHolder(new ConnectionHolder(newCon), true);}txObject.getConnectionHolder().setSynchronizedWithTransaction(true);//從事務(wù)對(duì)象獲取Connectioncon = txObject.getConnectionHolder().getConnection();//事務(wù)準(zhǔn)備,返回隔離級(jí)別,并設(shè)置到當(dāng)前事務(wù)對(duì)象。Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);txObject.setPreviousIsolationLevel(previousIsolationLevel);txObject.setReadOnly(definition.isReadOnly());// 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).//是否自動(dòng)提交。如果是自動(dòng)提交,則改為手動(dòng)提交。if (con.getAutoCommit()) {txObject.setMustRestoreAutoCommit(true);if (logger.isDebugEnabled()) {logger.debug("Switching JDBC Connection [" + con + "] to manual commit");}con.setAutoCommit(false);}//準(zhǔn)備提交。prepareTransactionalConnection(con, definition);//激活當(dāng)前事務(wù)。txObject.getConnectionHolder().setTransactionActive(true);//設(shè)置超時(shí)。int timeout = determineTimeout(definition);if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {txObject.getConnectionHolder().setTimeoutInSeconds(timeout);}// 如果是新建的,則綁定到當(dāng)前線程。if (txObject.isNewConnectionHolder()) {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);}}?doCommit
通過(guò)事務(wù)的Connection,調(diào)用commit方法,提交事務(wù)。
@Overrideprotected void doCommit(DefaultTransactionStatus status) { //從事務(wù)對(duì)象中獲取Connection,調(diào)用Connection的提交。DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();Connection con = txObject.getConnectionHolder().getConnection();if (status.isDebug()) {logger.debug("Committing JDBC transaction on Connection [" + con + "]");}try {con.commit();}catch (SQLException ex) {throw new TransactionSystemException("Could not commit JDBC transaction", ex);}}doSuspend
Connection設(shè)置為null,解綁資源
@Overrideprotected Object doSuspend(Object transaction) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;txObject.setConnectionHolder(null); //當(dāng)前線程解綁資源,return TransactionSynchronizationManager.unbindResource(obtainDataSource());}@Overrideprotected void doResume(@Nullable Object transaction, Object suspendedResources) { //重新綁定資源TransactionSynchronizationManager.bindResource(obtainDataSource(), suspendedResources);}doRollback
調(diào)用Connection.rollback()方法回滾事務(wù)。
@Overrideprotected 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);}}doCleanupAfterCompletion
如果新事務(wù),解綁資源。恢復(fù)狀態(tài):自動(dòng)提交、connection。
@Overrideprotected void doCleanupAfterCompletion(Object transaction) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;// Remove the connection holder from the thread, if exposed.if (txObject.isNewConnectionHolder()) {TransactionSynchronizationManager.unbindResource(obtainDataSource());}// Reset connection.Connection con = txObject.getConnectionHolder().getConnection();try {if (txObject.isMustRestoreAutoCommit()) {con.setAutoCommit(true);}DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel(), txObject.isReadOnly());}catch (Throwable ex) {logger.debug("Could not reset JDBC Connection after transaction", ex);}if (txObject.isNewConnectionHolder()) {if (logger.isDebugEnabled()) {logger.debug("Releasing JDBC Connection [" + con + "] after transaction");}DataSourceUtils.releaseConnection(con, this.dataSource);}txObject.getConnectionHolder().clear();}DataSourceUtils
DataSourceUtils,工具類,用于輔助DataSource操作。主要就是Connection相關(guān)操作,
ConnectionSynchronization
用于事務(wù)同步。
private final ConnectionHolder connectionHolder;private final DataSource dataSource;private int order;private boolean holderActive = true;?suspend
解綁datasource資源,釋放connection。
@Overridepublic void suspend() {if (this.holderActive) {TransactionSynchronizationManager.unbindResource(this.dataSource);if (this.connectionHolder.hasConnection() && !this.connectionHolder.isOpen()) {// Release Connection on suspend if the application doesn't keep// a handle to it anymore. We will fetch a fresh Connection if the// application accesses the ConnectionHolder again after resume,// assuming that it will participate in the same transaction.releaseConnection(this.connectionHolder.getConnection(), this.dataSource);this.connectionHolder.setConnection(null);}}} @Overridepublic void resume() {if (this.holderActive) {TransactionSynchronizationManager.bindResource(this.dataSource, this.connectionHolder);}} @Overridepublic void beforeCompletion() {// Release Connection early if the holder is not open anymore// (that is, not used by another resource like a Hibernate Session// that has its own cleanup via transaction synchronization),// to avoid issues with strict JTA implementations that expect// the close call before transaction completion.if (!this.connectionHolder.isOpen()) {TransactionSynchronizationManager.unbindResource(this.dataSource);this.holderActive = false;if (this.connectionHolder.hasConnection()) {releaseConnection(this.connectionHolder.getConnection(), this.dataSource);}}}@Overridepublic void afterCompletion(int status) {// If we haven't closed the Connection in beforeCompletion,// close it now. The holder might have been used for other// cleanup in the meantime, for example by a Hibernate Session.if (this.holderActive) {// The thread-bound ConnectionHolder might not be available anymore,// since afterCompletion might get called from a different thread.TransactionSynchronizationManager.unbindResourceIfPossible(this.dataSource);this.holderActive = false;if (this.connectionHolder.hasConnection()) {releaseConnection(this.connectionHolder.getConnection(), this.dataSource);// Reset the ConnectionHolder: It might remain bound to the thread.this.connectionHolder.setConnection(null);}}this.connectionHolder.reset();}?
總結(jié)
以上是生活随笔為你收集整理的Spring Boot Transaction 源码解析(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 高性能Mysql--Schema与数据类
- 下一篇: Spring的@Configuratio