Spring各种传播特性源码实现的概览

这几天都在分析Spring的源码实现,看到事务管理的部分

  我们知道事务的传播特性有下面几种,我标黄的就是最常用的3中传播特性, Sping在发生事务嵌套的时候,会依据内层事务的传播特性,来决定内层是事务的行为

  对于传播特性的处理,一定是在外层已经存在事务的情况下进行的, 使用了AOP事务管理 那么在执行外层方法前,进入代理的时候就会调用getTransaction(txAttr)方法来开启事务,此时因为还没有ConnectionHolder创建出来,所以一定会去创建Connection 和 ConnectionHolder 以及开启事务的,这个时候 spring不会关系外层方法对于的事务的传播特性,此时的传播特性也没有什么意义. 

  到了第二层,这个传播特性才开始起作用了,在外层已经有事务开启的情况下,本层的方法是开启新事务,还是加入上层的事务,还是报错,等等举动,就都取决于这个传播特性了.

   

  • PROPAGATION_MANDATORY  方法必须在事务中运行,如果没有事务就要抛出错误 MANDATORY 是强制的意思
  • PROPAGATION_NESTED   嵌套,外层有事务的情况下 如果内层要打开事务就打开事务嵌套运行,如果内层没有事务就加入到上层事务中去,嵌套事务是可以独立提交和回滚的 (对于jdbc Spring其实在内层没有开启新事务,只是在内层方法前设置了savepoint)
  • PROPAGATION_NEVER  表示这个方法不能运行在事务中,如果上下文有事务 就要抛出异常
  • PROPAGATION_NOT_SUPPORTED 表示当前方法运行的时候 如果有上下文事务,那么上下文事务会被挂起 等该方法执行结束,上下文事务恢复
  • PROPAGATION_REQUIRED  表示当前方法必须运行在事务中,如果上下文有事务就加入上下文事务;上下文没有事务,就启动一个新事务
  • PROPAGATION_REQUIRES_NEW  当前方法一定会启动自己的事务,如果有上下文事务,上下文事务会被挂起的 (对于jdbc  Spring在内层开启新事务(创建了新的Connection  内层事务是独立的开启 提交 回滚的)
  • PROPAGATION_SUPPORTS 表示当前方法不需要上下文事务,但是如果有上下文事务的话 还是可以在上下文事务里运行的
     
    对于不同的传播特性 做出不同的处理,这个逻辑所在的核心方法就是AbstractPlatformTransactionManager类中的handleExistingTransaction方法
看源码摘录:
  1     /**
  2      * Create a TransactionStatus for an existing transaction.
  3      */
  4     private TransactionStatus handleExistingTransaction(
  5             TransactionDefinition definition, Object transaction, boolean debugEnabled)
  6             throws TransactionException {
  7  
  8         //PROPAGATION_NEVER 就是不能再事务环境中运行 如果外层有事务了 就直接抛错
  9         if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
 10             throw new IllegalTransactionStateException(
 11                     "Existing transaction found for transaction marked with propagation 'never'");
 12         }
 13  
 14 
 15         //PROPAGATION_NOT_SUPPORTED 也表示不能运行在上下文事务中,但是不会抛出 会把外层事务挂起
 16         if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
 17             if (debugEnabled) {
 18                 logger.debug("Suspending current transaction");
 19             }
 20             //开始挂起外层事务  这会把外层事务的ConnectionHolder ,names isolation 等等属性存到suspendedResources  然后suspendedResources 存到
 21 //本层事务对于的TransactionStatus对象里面
 22             //然后会清除TransactionSynchronizationManager里面的ThreadLocal属性 包括线程绑定的ConnectionHolder ,于是本层dao方法中如果要访问数据库就不能取ThreadLocal里的Connection了 
 23 //得自己新建Connection,自然就实现了脱离外层事务的目的
 24             //等到本层dao方法结束,进行commit的时候 会跳过doCommit方法 执行resume方法 恢复外层事务
 25             Object suspendedResources = suspend(transaction); 
 26            
 27             //newSynchronization 肯定是false
 28             boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
 29             return prepareTransactionStatus(definition, null, false, newSynchronization, debugEnabled, suspendedResources);
 30         }
 31  
 32         //PROPAGATION_REQUIRES_NEW 会在本层开启新的事务  挂起上层事务
 33         if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
 34             if (debugEnabled) {
 35                 logger.debug("Suspending current transaction, creating new transaction with name [" +
 36                         definition.getName() + "]");
 37             }
 38             //挂起上层事务
 39             SuspendedResourcesHolder suspendedResources = suspend(transaction);
 40             try {
 41                 //开启本层新事务
 42                 boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);//也是true
 43                 //创建txStatus对象 isNewTransaction是true
 44                 DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
 45                 //执行conn.setAutoCommit(false) 以及ConnectionHolder状态设置,以及ConnectionHolder线程绑定
 46                 doBegin(transaction, definition);
 47                 //TransactionSynchronizationManager属性填充
 48                 prepareSynchronization(status, definition);
 49 
 50                 return status;
 51             }
 52             catch (RuntimeException beginEx) {
 53                 //如果出异常 就恢复上层事务
 54                 resumeAfterBeginException(transaction, suspendedResources, beginEx);
 55                 throw beginEx;
 56             }
 57             catch (Error beginErr) {
 58                 resumeAfterBeginException(transaction, suspendedResources, beginErr);
 59                 throw beginErr;
 60             }
 61         }
 62  
 63      
 64         //PROPAGATION_NESTED 是嵌套,但是spring实现jdbc的嵌套并没有开启事务,而是通过设置savepoint来实现的
 65         if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
 66             if (!isNestedTransactionAllowed()) {
 67                 throw new NestedTransactionNotSupportedException(
 68                         "Transaction manager does not allow nested transactions by default - " +
 69                         "specify 'nestedTransactionAllowed' property with value 'true'");
 70             }
 71             if (debugEnabled) {
 72                 logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
 73             }
 74             //如果允许使用savepoint来实现Nest
 75             if (useSavepointForNestedTransaction()) {
 76                 // Create savepoint within existing Spring-managed transaction,
 77                 // through the SavepointManager API implemented by TransactionStatus.
 78                 // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
 79                 //不开启新事务 直接创建txStatus 
 80                 DefaultTransactionStatus status = prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
 81                 //创建savepoint
 82                 status.createAndHoldSavepoint();
 83                 return status;
 84             }
 85             else {
 86                 //如果不允许使用savepoint 那就和PROPAGATION_REQUIRES_NEW 是一样的 本层开启全新事务  区别在于 这里是没有对上层事务做挂起
 87                 //这种事情主要用在JTA事务
 88                 // Nested transaction through nested begin and commit/rollback calls.
 89                 // Usually only for JTA: Spring synchronization might get activated here
 90                 // in case of a pre-existing JTA transaction.
 91                 boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
 92                 DefaultTransactionStatus status = newTransactionStatus(
 93                         definition, transaction, true, newSynchronization, debugEnabled, null);
 94                 doBegin(transaction, definition);
 95                 prepareSynchronization(status, definition);
 96                 return status;
 97             }
 98         }
 99  
100  
101  
102  
103         
104         // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
105         if (debugEnabled) {
106             logger.debug("Participating in existing transaction");
107         }
108         if (isValidateExistingTransaction()) {
109             if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
110                 Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
111                 if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
112                     Constants isoConstants = DefaultTransactionDefinition.constants;
113                     throw new IllegalTransactionStateException("Participating transaction with definition [" +
114                             definition + "] specifies isolation level which is incompatible with existing transaction: " +
115                             (currentIsolationLevel != null ?
116                                     isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
117                                     "(unknown)"));
118                 }
119             }
120             if (!definition.isReadOnly()) {
121                 if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
122                     throw new IllegalTransactionStateException("Participating transaction with definition [" +
123                             definition + "] is not marked as read-only but existing transaction is");
124                 }
125             }
126         }
127  
128         //PROPAGATION_SUPPORTS  和 PROPAGATION_REQUIRED的情况  处理方式是一样的 也就是不做任何处理 直接生产TransactionStatus对象就返回了 本层直接加入上层事务
129         boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
130         return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
131     }

 

 
 
posted @ 2015-01-21 16:51  wz1989  阅读(303)  评论(0编辑  收藏  举报