面试官:问你一个,Spring事务是如何传播的?( 四 )

这个方法里面主要做了六件事:

  • 首先从连接池获取连接并保存到DataSourceTransactionObject对象中 。
  • 关闭数据库的自动提交 , 也就是开启事务 。
  • 获取数据库的隔离级别 。
  • 根据属性设置该事务是否为只读事务 。
  • 将该事务标识为活动事务(transactionActive=true) 。
  • 将ConnectionHolder对象与当前线程绑定 。
完成之后通过prepareSynchronization将事务的属性和状态设置到TransactionSynchronizationManager对象中进行管理 。 最后返回到createTransactionIfNecessary方法中创建TransactionInfo对象与当前线程绑定并返回 。 通过以上的步骤就开启了事务 , 接下来就是通过proceedWithInvocation调用其它切面 , 这里我们先假设没有其它切面了 , 那么就是直接调用到A类的addA方法 , 在这个方法中又调用了B类的addB方法 , 那么肯定也是调用到代理类的方法 , 因此又会进入到createTransactionIfNecessary方法中 。 但这次进来通过isExistingTransaction判断是存在事务的 , 因此会进入到handleExistingTransaction方法:
private TransactionStatus handleExistingTransaction(TransactionDefinition definition, Object transaction, boolean debugEnabled)throws TransactionException {//不允许有事务 , 直接异常if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {throw new IllegalTransactionStateException("Existing transaction found for transaction marked with propagation 'never'");}//以非事务方式执行操作 , 如果当前存在事务 , 就把当前事务挂起if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {if (debugEnabled) {logger.debug("Suspending current transaction");}//挂起当前事务Object suspendedResources = suspend(transaction);boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);//修改事务状态信息 , 把事务的一些信息存储到当前线程中 , ThreadLocal中return prepareTransactionStatus(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() + "]");}//挂起SuspendedResourcesHolder suspendedResources = suspend(transaction);try {boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);doBegin(transaction, definition);prepareSynchronization(status, definition);return status;}catch (RuntimeException | Error beginEx) {resumeAfterBeginException(transaction, suspendedResources, beginEx);throw beginEx;}}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 =prepareTransactionStatus(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.boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);doBegin(transaction, definition);prepareSynchronization(status, definition);return status;}}// 省略boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null); }


推荐阅读