spring提交事务-源码分析

494 阅读5分钟

说明

本文主要是讲spring提交事务的时候,发生了什么,主要是源码分析和源码流程。

service类的业务方法执行完成

在return之前,进入spring事务拦截器。

spring事务拦截器

TransactionAspectSupport

/**
 * General delegate for around-advice-based subclasses, delegating to several other template
 * methods on this class. Able to handle {@link CallbackPreferringPlatformTransactionManager}
 * as well as regular {@link PlatformTransactionManager} implementations.
 * @param method the Method being invoked
 * @param targetClass the target class that we're invoking the method on
 * @param invocation the callback to use for proceeding with the target invocation
 * @return the return value of the method, if any
 * @throws Throwable propagated from the target invocation
 */
protected Object invokeWithinTransaction(Method method, Class targetClass, final InvocationCallback invocation)
  throws Throwable {

 // If the transaction attribute is null, the method is non-transactional.
 final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
 final PlatformTransactionManager tm = determineTransactionManager(txAttr);
 final String joinpointIdentification = methodIdentification(method, targetClass);

 if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
  // Standard transaction demarcation with getTransaction and commit/rollback calls.
  TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, 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.
   retVal = invocation.proceedWithInvocation(); //查询
  }
  catch (Throwable ex) {
   // target invocation exception
   completeTransactionAfterThrowing(txInfo, ex);
   throw ex;
  }
  finally {
   cleanupTransactionInfo(txInfo); //
  }
  commitTransactionAfterReturning(txInfo); //提交事务
  return retVal;
 }
/**
 * Execute after successful completion of call, but not after an exception was handled.
 * Do nothing if we didn't create a transaction.
 * @param txInfo information about the current transaction
 */
protected void commitTransactionAfterReturning(TransactionInfo txInfo) {
 if (txInfo != null && txInfo.hasTransaction()) {
  if (logger.isTraceEnabled()) {
   logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
  }
  txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); //1.获取事务管理器 2.提交事务
 }
}

AbstractPlatformTransactionManager

/**
 * This implementation of commit handles participating in existing
 * transactions and programmatic rollback requests.
 * Delegates to {@code isRollbackOnly}, {@code doCommit}
 * and {@code rollback}.
 * @see org.springframework.transaction.TransactionStatus#isRollbackOnly()
 * @see #doCommit
 * @see #rollback
 */
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); //提交事务
}
/**
 * Process an actual commit.
 * Rollback-only flags have already been checked and applied.
 * @param status object representing the transaction
 * @throws TransactionException in case of commit failure
 */
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); //提交事务
   }
   // Throw UnexpectedRollbackException if we have a global rollback-only
   // marker but still didn't get a corresponding exception from commit.
   if (globalRollbackOnly) {
    throw new UnexpectedRollbackException(
      "Transaction silently rolled back because it has been marked as rollback-only");
   }
  }
  catch (UnexpectedRollbackException ex) {
   // can only be caused by doCommit
   triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
   throw ex;
  }
  catch (TransactionException ex) {
   // can only be caused by doCommit
   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;
  }

  // Trigger afterCommit callbacks, with an exception thrown there
  // propagated to callers but the transaction still considered as committed.
  try {
   triggerAfterCommit(status);
  }
  finally {
   triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
  }

 }
 finally {
  cleanupAfterCompletion(status); //释放事务资源
 }
}

HibernateTransactionManager

@Override
protected void doCommit(DefaultTransactionStatus status) {
 HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction(); //获取hibernate事务对象
 if (status.isDebug()) {
  logger.debug("Committing Hibernate transaction on Session [" +
    SessionFactoryUtils.toString(txObject.getSessionHolder().getSession()) + "]");
 }
 try {
  txObject.getSessionHolder().getTransaction().commit(); //提交事务
 }
 catch (org.hibernate.TransactionException ex) {
  // assumably from commit call to the underlying JDBC connection
  throw new TransactionSystemException("Could not commit Hibernate transaction", ex);
 }
 catch (HibernateException ex) {
  // assumably failed to flush changes to database
  throw convertHibernateAccessException(ex);
 }
}

hibernate

JDBCTransaction

public void commit() throws HibernateException {
  if (!this.begun) {
    throw new TransactionException("Transaction not successfully started");
  } else {
    log.debug("commit");
    if (!this.transactionContext.isFlushModeNever() && this.callback) {
      this.transactionContext.managedFlush();
    }

    this.notifySynchronizationsBeforeTransactionCompletion();
    if (this.callback) {
      this.jdbcContext.beforeTransactionCompletion(this);
    }

    try {
      this.commitAndResetAutoCommit(); //提交事务
      log.debug("committed JDBC Connection");
      this.committed = true;
      if (this.callback) {
        this.jdbcContext.afterTransactionCompletion(true, this);
      }

      this.notifySynchronizationsAfterTransactionCompletion(3);
    } catch (SQLException var6) {
      log.error("JDBC commit failed", var6);
      this.commitFailed = true;
      if (this.callback) {
        this.jdbcContext.afterTransactionCompletion(false, this);
      }

      this.notifySynchronizationsAfterTransactionCompletion(5);
      throw new TransactionException("JDBC commit failed", var6);
    } finally {
      this.closeIfRequired();
    }

  }
}
private void commitAndResetAutoCommit() throws SQLException {
  try {
    this.jdbcContext.connection().commit(); //提交事务
  } finally {
    this.toggleAutoCommit();
  }

}

dbcp

PoolingDataSource

public void commit() throws SQLException {
  this.checkOpen();
  this.delegate.commit(); //提交事务
}

jdbc-oracle

PhysicalConnection

public void commit() throws SQLException {
  this.commit(this.commitOption);
}
synchronized void commit(int var1) throws SQLException {
  this.disallowGlobalTxnMode(114);
  if (this.lifecycle != 1) {
    SQLException var4 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 8);
    var4.fillInStackTrace();
    throw var4;
  } else {
    for(OracleStatement var2 = this.statements; var2 != null; var2 = var2.next) {
      if (!var2.closed) {
        var2.sendBatch();
      }
    }

    if (((var1 & CommitOption.WRITEBATCH.getCode()) == 0 || (var1 & CommitOption.WRITEIMMED.getCode()) == 0) && ((var1 & CommitOption.WAIT.getCode()) == 0 || (var1 & CommitOption.NOWAIT.getCode()) == 0)) {
      this.registerHeartbeat();
      this.needLine();
      this.doCommit(var1); //提交事务
    } else {
      SQLException var3 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 191);
      var3.fillInStackTrace();
      throw var3;
    }
  }
}

T4CConnection

synchronized void doCommit(int var1) throws SQLException {
  this.assertLoggedOn("T4CConnection.do_commit");

  try {
    this.sendPiggyBackedMessages();
    if (var1 == 0) {
      this.commoncall.doOCOMMIT(); //提交事务
    } else {
      int var2 = 0;
      if ((var1 & CommitOption.WRITEBATCH.getCode()) != 0) {
        var2 = var2 | 2 | 1;
      } else if ((var1 & CommitOption.WRITEIMMED.getCode()) != 0) {
        var2 |= 2;
      }

      if ((var1 & CommitOption.NOWAIT.getCode()) != 0) {
        var2 = var2 | 8 | 4;
      } else if ((var1 & CommitOption.WAIT.getCode()) != 0) {
        var2 |= 8;
      }

      this.otxen.doOTXEN(1, (byte[])null, (byte[])null, 0, 0, 0, 0, 4, var2);
      int var5 = this.otxen.getOutStateFromServer();
      if (var5 != 2 && var5 != 4) {
      }
    }

  } catch (IOException var4) {
    this.handleIOException(var4);
    SQLException var3 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), var4);
    var3.fillInStackTrace();
    throw var3;
  }
}

T4C7Ocommoncall

void doOCOMMIT() throws SQLException, IOException {
  this.setFunCode((short)14);
  this.doRPC();
}

T4CTTIfun

final void doRPC() throws IOException, SQLException {
  if (this.getTTCCode() == 17) {
    SQLException var12 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 401);
    var12.fillInStackTrace();
    throw var12;
  } else {
    for(int var1 = 0; var1 < 5; ++var1) {
      this.init();
      this.marshalFunHeader();

      try {
        this.connection.pipeState = 1;
        this.marshal();
        this.connection.pipeState = 2;
        this.receive(); //与oracle通信
        break;
      } catch (SQLException var10) {
        SQLException var2 = var10;
        synchronized(this.connection.cancelInProgressLockForThin) {
          if (var2.getErrorCode() == 1013 || this.connection.cancelInProgressFlag && var2.getMessage() != null && var2.getMessage().contains("ORA-01013")) {
            this.connection.cancelInProgressFlag = false;
            this.connection.redoCursorClose();
            if ((this.funCode == 15 || this.funCode == 12 || this.funCode == 13 || this.funCode == 14 || this.funCode == 59) && (this.oer.callNumber != this.connection.currentTTCSeqNumber || this.connection.statementCancel)) {
              continue;
            }
          }
        }

        throw var10;
      } finally {
        this.connection.pipeState = -1;
      }
    }

  }
}
private void receive() throws SQLException, IOException {
  this.receiveState = 1;
  SQLException var1 = null;

  label250:
  while(true) {
    while(true) {
      try {
        short var2 = this.meg.unmarshalUB1();
        this.ttilist.add(new Short(var2));
        switch(var2) {
        case 4:
          this.processEOCS();
          this.oer.init();
          this.oer.unmarshal();

          try {
            this.processError();
          } catch (SQLException var14) {
            var1 = var14;
          }
          break label250;
        case 5:
        case 10:
        case 13:
        case 17:
        case 18:
        case 20:
        case 22:
        default:
          SQLException var24 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 401, this.ttilist.toString());
          var24.fillInStackTrace();
          throw var24;
        case 6:
          this.readRXH();
          this.rxhProcessed = true;
          break;
        case 7:
          this.receiveState = 2;
          if (this.readRXD()) {
            this.receiveState = 3;
            return;
          }

          this.receiveState = 1;
          break;
        case 8:
          if (this.rpaProcessed) {
            SQLException var19 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 401);
            var19.fillInStackTrace();
            throw var19;
          }

          this.readRPA();

          try {
            this.processRPA();
          } catch (SQLException var16) {
            var1 = var16;
          }

          this.rpaProcessed = true;
          break;
        case 9:
          this.processEOCS(); //与oracle通信
          if (this.connection.getTTCVersion() >= 3) {
            short var23 = (short)this.meg.unmarshalUB2();
            this.connection.endToEndECIDSequenceNumber = var23;
          }
          break label250;
        case 11:
          this.readIOV();
          this.iovProcessed = true;
          break;
        case 12:
          this.processSLG();
          break;
        case 14:
          this.readLOBD();
          break;
        case 15:
          this.oer.init();
          this.oer.unmarshalWarning();

          try {
            this.oer.processWarning();
          } catch (SQLWarning var15) {
            this.connection.setWarnings(DatabaseError.addSqlWarning(this.connection.getWarnings(), var15));
          }
          break;
        case 16:
          this.readDCB();
          break;
        case 19:
          this.meg.marshalUB1((short)19);
          break;
        case 21:
          this.readBVC();
          break;
        case 23:
          byte var3 = (byte)this.meg.unmarshalUB1();
          int var4 = this.meg.unmarshalUB2();
          byte var5 = (byte)this.meg.unmarshalUB1();
          int var20;
          if (var3 == 1) {
            for(var20 = 0; var20 < var4; ++var20) {
              T4CTTIidc var22 = new T4CTTIidc(this.connection);
              var22.unmarshal();
            }
          } else if (var3 == 2) {
            for(var20 = 0; var20 < var4; ++var20) {
              short var21 = this.meg.unmarshalUB1();
            }
          } else if (var3 != 3 && var3 != 4) {
            if (var3 != 5) {
              if (var3 == 6) {
                for(var20 = 0; var20 < var4; ++var20) {
                  NTFXSEvent var7 = new NTFXSEvent(this.connection);
                  this.connection.notify(var7);
                }
              }
            } else {
              T4CTTIkvarr var6 = new T4CTTIkvarr(this.connection);
              var6.unmarshal();
            }
          }
        }
      } catch (BreakNetException var17) {
      } finally {
        this.connection.sentCancel = false;
      }
    }
  }

  this.receiveState = 0;
  if (var1 != null) {
    throw var1;
  }
}
private final void processEOCS() throws SQLException, IOException {
  if (this.connection.hasServerCompileTimeCapability(15, 1)) {
    int var1 = (int)this.meg.unmarshalUB4(); //与oralce通信
    this.connection.eocs = var1;
    if ((var1 & 8) != 0) {
      long var2 = this.meg.unmarshalSB8();
    }
  }

}

又回到hibernate-JDBCTransaction

private void commitAndResetAutoCommit() throws SQLException {
  try {
    this.jdbcContext.connection().commit(); //方法返回
  } finally {
    this.toggleAutoCommit(); //这里的值是false,非自动提交。所以每次都要spring事务和hibernate来提交事务,说白了就是禁用了jdbc Connection的自动提交,然后由上层spring和hibernate来提交事务。
  }

}
public void commit() throws HibernateException {
  if (!this.begun) {
    throw new TransactionException("Transaction not successfully started");
  } else {
    log.debug("commit");
    if (!this.transactionContext.isFlushModeNever() && this.callback) {
      this.transactionContext.managedFlush();
    }

    this.notifySynchronizationsBeforeTransactionCompletion();
    if (this.callback) {
      this.jdbcContext.beforeTransactionCompletion(this);
    }

    try {
      this.commitAndResetAutoCommit(); //方法返回
      log.debug("committed JDBC Connection");
      this.committed = true; //
      if (this.callback) {
        this.jdbcContext.afterTransactionCompletion(true, this);
      }

      this.notifySynchronizationsAfterTransactionCompletion(3);
    } catch (SQLException var6) {
      log.error("JDBC commit failed", var6);
      this.commitFailed = true;
      if (this.callback) {
        this.jdbcContext.afterTransactionCompletion(false, this);
      }

      this.notifySynchronizationsAfterTransactionCompletion(5);
      throw new TransactionException("JDBC commit failed", var6);
    } finally {
      this.closeIfRequired();
    }

  }
}

又回到spring事务拦截器

AbstractPlatformTransactionManager

/**
 * Process an actual commit.
 * Rollback-only flags have already been checked and applied.
 * @param status object representing the transaction
 * @throws TransactionException in case of commit failure
 */
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); //方法返回
   }
   // Throw UnexpectedRollbackException if we have a global rollback-only
   // marker but still didn't get a corresponding exception from commit.
   if (globalRollbackOnly) {
    throw new UnexpectedRollbackException(
      "Transaction silently rolled back because it has been marked as rollback-only");
   }
  }
  catch (UnexpectedRollbackException ex) {
   // can only be caused by doCommit
   triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
   throw ex;
  }
  catch (TransactionException ex) {
   // can only be caused by doCommit
   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;
  }

  // Trigger afterCommit callbacks, with an exception thrown there
  // propagated to callers but the transaction still considered as committed.
  try {
   triggerAfterCommit(status);
  }
  finally {
   triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
  }

 }
 finally {
  cleanupAfterCompletion(status); //释放事务资源
 }
}
/**
 * Clean up after completion, clearing synchronization if necessary,
 * and invoking doCleanupAfterCompletion.
 * @param status object representing the transaction
 * @see #doCleanupAfterCompletion
 */
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
 status.setCompleted();
 if (status.isNewSynchronization()) { //如果是新的事务锁
  TransactionSynchronizationManager.clear(); //释放事务资源
 }
 if (status.isNewTransaction()) { //如果是新的事务
  doCleanupAfterCompletion(status.getTransaction()); //继续释放事务资源
 }
 if (status.getSuspendedResources() != null) {
  if (status.isDebug()) {
   logger.debug("Resuming suspended transaction after completion of inner transaction");
  }
  resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources());
 }
}

释放事务锁

TransactionSynchronizationManager

/**
  * Clear the entire transaction synchronization state for the current thread:
  * registered synchronizations as well as the various transaction characteristics.
  * @see #clearSynchronization()
  * @see #setCurrentTransactionName
  * @see #setCurrentTransactionReadOnly
  * @see #setCurrentTransactionIsolationLevel
  * @see #setActualTransactionActive
  */
 public static void clear() {
  clearSynchronization(); //删除事务锁
  setCurrentTransactionName(null);
  setCurrentTransactionReadOnly(false);
  setCurrentTransactionIsolationLevel(null);
  setActualTransactionActive(false);
 }

}
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
  new NamedThreadLocal<Set<TransactionSynchronization>>("Transaction synchronizations"); //每个请求线程都有一个事务锁
/**
 * Deactivate transaction synchronization for the current thread.
 * Called by the transaction manager on transaction cleanup.
 * @throws IllegalStateException if synchronization is not active
 */
public static void clearSynchronization() throws IllegalStateException {
 if (!isSynchronizationActive()) {
  throw new IllegalStateException("Cannot deactivate transaction synchronization - not active");
 }
 logger.trace("Clearing transaction synchronization");
 synchronizations.remove(); //删除事务锁
}

HibernateTransactionManager

@Override
protected void doCleanupAfterCompletion(Object transaction) {
 HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;

 // Remove the session holder from the thread.
 if (txObject.isNewSessionHolder()) {
  TransactionSynchronizationManager.unbindResource(getSessionFactory()); //释放会话工厂
 }

 // Remove the JDBC connection holder from the thread, if exposed.
 if (getDataSource() != null) {
  TransactionSynchronizationManager.unbindResource(getDataSource()); //释放连接池的数据库连接
 }

 Session session = txObject.getSessionHolder().getSession();
 if (this.prepareConnection && session.isConnected() && isSameConnectionForEntireSession(session)) {
  // We're running with connection release mode "on_close": We're able to reset
  // the isolation level and/or read-only flag of the JDBC Connection here.
  // Else, we need to rely on the connection pool to perform proper cleanup.
  try {
   Connection con = session.connection();
   DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel()); //
  }
  catch (HibernateException ex) {
   logger.debug("Could not access JDBC Connection of Hibernate Session", ex);
  }
 }

 if (txObject.isNewSession()) {
  if (logger.isDebugEnabled()) {
   logger.debug("Closing Hibernate Session [" + SessionFactoryUtils.toString(session) +
     "] after transaction");
  }
  SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory()); //关闭会话对象
 }
 else {
  if (logger.isDebugEnabled()) {
   logger.debug("Not closing pre-bound Hibernate Session [" +
     SessionFactoryUtils.toString(session) + "] after transaction");
  }
  if (txObject.getSessionHolder().getPreviousFlushMode() != null) {
   session.setFlushMode(txObject.getSessionHolder().getPreviousFlushMode());
  }
  if (!this.hibernateManagedSession) {
   session.disconnect();
  }
 }
 txObject.getSessionHolder().clear();
}

删除当前线程的map:连接池对象/连接对象

/**
 * Actually remove the value of the resource that is bound for the given key.
 */
private static Object doUnbindResource(Object actualKey) {
 Map<Object, Object> map = resources.get(); //获取map:连接池对象/连接对象
 if (map == null) {
  return null;
 }
 Object value = map.remove(actualKey); 
 // Remove entire ThreadLocal if empty...
 if (map.isEmpty()) { //
  resources.remove(); //删除当前线程的map:连接池对象/连接对象
 }
 // Transparently suppress a ResourceHolder that was marked as void...
 if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
  value = null;
 }
 if (value != null && logger.isTraceEnabled()) {
  logger.trace("Removed value [" + value + "] for key [" + actualKey + "] from thread [" +
    Thread.currentThread().getName() + "]");
 }
 return value;
}

调用栈

doUnbindResource:239, TransactionSynchronizationManager (org.springframework.transaction.support)
unbindResource:207, TransactionSynchronizationManager (org.springframework.transaction.support)
doCleanupAfterCompletion:716, HibernateTransactionManager (org.springframework.orm.hibernate3) //事务管理器:释放资源,比如后面会调用hibernate,hibernate又会调用连接池,来归还连接到连接池
cleanupAfterCompletion:1009, AbstractPlatformTransactionManager (org.springframework.transaction.support)
processCommit:805, AbstractPlatformTransactionManager (org.springframework.transaction.support)
commit:724, AbstractPlatformTransactionManager (org.springframework.transaction.support)
commitTransactionAfterReturning:475, TransactionAspectSupport (org.springframework.transaction.interceptor)
invokeWithinTransaction:270, TransactionAspectSupport (org.springframework.transaction.interceptor)
invoke:94, TransactionInterceptor (org.springframework.transaction.interceptor) //spring事务拦截器
proceed:172, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:91, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:172, ReflectiveMethodInvocation (org.springframework.aop.framework)
intercept:631, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework) //spring拦截器

merModifyNoAudit:-1, UrmtminfService$$EnhancerByCGLIB$$37eb7ff (xxx.qrcode.register.dbservice.impl)
merModifyNoAudit:517, QrcodeRegisterServer (xxx.qrcode.register.remoteserver.impl) //应用程序入口
invokeMethod:-1, Wrapper20 (com.alibaba.dubbo.common.bytecode)
doInvoke:47, JavassistProxyFactory$1 (com.alibaba.dubbo.rpc.proxy.javassist)
invoke:76, AbstractProxyInvoker (com.alibaba.dubbo.rpc.proxy)
invoke:52, DelegateProviderMetaDataInvoker (com.alibaba.dubbo.config.invoker)
invoke:56, InvokerWrapper (com.alibaba.dubbo.rpc.protocol)
invoke:11, AppNameAppendFilter (com.xxx.log.rpc.dubbo)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:62, ExceptionFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:42, TimeoutFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:60, ExecuteLimitFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:75, MonitorFilter (com.alibaba.dubbo.monitor.support)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:78, TraceFilter (com.alibaba.dubbo.rpc.protocol.dubbo.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:84, AccessLogExtFilter (xxx.qrcode.common.filter.dubbo)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:82, CatTransaction (com.xxx.log.rpc.dubbo)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:73, ContextFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:138, GenericFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:38, ClassLoaderFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:38, EchoFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
reply:104, DubboProtocol$1 (com.alibaba.dubbo.rpc.protocol.dubbo)
handleRequest:96, HeaderExchangeHandler (com.alibaba.dubbo.remoting.exchange.support.header)
received:173, HeaderExchangeHandler (com.alibaba.dubbo.remoting.exchange.support.header)
received:51, DecodeHandler (com.alibaba.dubbo.remoting.transport)
run:57, ChannelEventRunnable (com.alibaba.dubbo.remoting.transport.dispatcher)
runWorker:1145, ThreadPoolExecutor (java.util.concurrent)
run:615, ThreadPoolExecutor$Worker (java.util.concurrent)
run:745, Thread (java.lang)