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 }
学无止境-----博客均为原创,转载请注明出处