• spring 事务代码分析


    实际上,在spring的事务中,只要该类被设置为了事务代理:
     
    拦截器都会创建一个TransactionInfo 对象:
     

    TransactionInfo txInfo = new TransactionInfo(txAttr, method);

     
     
    而且如果 只要被调用的方法设置了事务属性(txAttr),不管是什么属性都会调用:
     

    txInfo.newTransactionStatus(this.transactionManager.getTransaction(txAttr));

     
    根据该方法的事务属性(definition )的不同,this.transactionManager.getTransaction(txAttr)的返回值会有所不同(代码见AbstractPlatformTransactionManager),具体为以下几种情况:
    1.当前没有事务时(即以下代码中的((HibernateTransactionObject) transaction).hasTransaction()返回false),会返回以下几种:
     
    // 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 behave.
      if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
       throw new IllegalTransactionStateException(
         "Transaction propagation 'mandatory' but no existing transaction found");
      }
      else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
        definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
          definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
       if (debugEnabled) {
        logger.debug("Creating new transaction with name [" + definition.getName() + "]");
       }
       doBegin(transaction, definition);
       boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
       return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);
      }
      else {
       // Create "empty" transaction: no actual transaction, but potentially synchronization.
       boolean newSynchronization = (this.transactionSynchronization == SYNCHRONIZATION_ALWAYS);
       return newTransactionStatus(definition, null, false, newSynchronization, debugEnabled, null);
      }
     
    2.当前有事务时
    private TransactionStatus handleExistingTransaction(
       TransactionDefinition definition, Object transaction, boolean debugEnabled)
       throws TransactionException {
     
      if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
       throw new IllegalTransactionStateException(
         "Transaction propagation 'never' but existing transaction found");
      }
     
      if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
       if (debugEnabled) {
        logger.debug("Suspending current transaction");
       }
       Object suspendedResources = suspend(transaction);
       boolean newSynchronization = (this.transactionSynchronization == SYNCHRONIZATION_ALWAYS);
       return newTransactionStatus(
         definition, null, false, newSynchronization, debugEnabled, suspendedResources);
      }
     
      if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
       if (debugEnabled) {
        logger.debug("Suspending current transaction, creating new transaction with name [" +
          definition.getName() + "]");
       }
       Object suspendedResources = suspend(transaction);
       doBegin(transaction, definition);
       boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
       return newTransactionStatus(
         definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
      }
     
      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() + "]");
       }
       if (useSavepointForNestedTransaction()) {
        // Create savepoint within existing Spring-managed transaction,
        // through the SavepointManager API implemented by TransactionStatus.
        // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
        DefaultTransactionStatus status =
          newTransactionStatus(definition, transaction, false, false, debugEnabled, null);
        status.createAndHoldSavepoint();
        return status;
       }
       else {
        // Nested transaction through nested begin and commit/rollback calls.
        // Usually only for JTA: Spring synchronization might get activated here
        // in case of a pre-existing JTA transaction.
        doBegin(transaction, definition);
        boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
        return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);
       }
      }
     
    最后,txInfo被绑定到当前线程上作为当前事务:
     

    txInfo.bindToThread()

     
    然后,调用实际的目标类的方法并捕捉异常:
     
    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.proceed();
      }
      catch (Throwable ex) {
       // target invocation exception
       doCloseTransactionAfterThrowing(txInfo, ex);
       throw ex;
      }
      finally {
       doFinally(txInfo);
      }
      doCommitTransactionAfterReturning(txInfo);
      return retVal;
     }
     
     
    另外一点,TransactionInfo的newTransactionStatus调用时如果参数的不是null,TransactionInfo.hasTransaction()方法返回true;
     
    重要提示:
    在spring中创建的事务代理类并是目标类的超类,只是一个实现这目标类接口的类,该类会调用目标类的方法,所在如果一个目标类中的方法调用自身的另一个事务方法,另一个方法只是作为普通方法来调用,并不会加入事务机制
     
    参考资料:
    1.Spring Reference Manual:http://static.springframework.org/spring/docs/1.2.x/reference/index.html
    2.Spring API doc:http://static.springframework.org/spring/docs/1.2.x/api/index.html
    3.Spring 的源代码
  • 相关阅读:
    Enable Zombie
    python中调用c文件中的函数(ubuntu)
    NSNotificationCenter使用心得(原)
    TCP/UDP
    xcconfig 文件使用( 转 )
    TS流解析 (转)
    c 数字和char类型转换
    结构体如何使用NSData包装
    NSValue 保存定长的结构体
    遍历DOM的所有节点,输出宽度高度都大于50的元素节点名称
  • 原文地址:https://www.cnblogs.com/huapox/p/3251478.html
Copyright © 2020-2023  润新知