唉,熟悉的知识总是看来看去,似乎是掌握了,重新整理思路的时候总会有疑问的地方。不熟悉的又害怕去看,怕是伤了自尊心。事务这块拖了很长时间了,昨天粗略看了下,依旧感觉力不从心。。不过没关系,现在看不懂,等能力提高了之后,再回看会发现轻松的。下面开始吧。。。
前一篇简单介绍了TransactionInterceptor,是一个方法拦截器,直接看invoke方法,为什么直接看这个方法呢?还记得哪里处理的逻辑吗?创建拦截器链的时候,会从链中取出一个,之后调用的就是invoke方法。。

org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction

     if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {// 开始事务的准备工作TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);Object retVal;try {// 执行目标方法,即用注解@transactional注解注释的方法。retVal = invocation.proceedWithInvocation();}catch (Throwable ex) {// 抛异常,回滚completeTransactionAfterThrowing(txInfo, ex);throw ex;}finally {cleanupTransactionInfo(txInfo);}if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {// Set rollback-only in case of Vavr failure matching our rollback rules...TransactionStatus status = txInfo.getTransactionStatus();if (status != null && txAttr != null) {retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);}}// 没有异常,提交。commitTransactionAfterReturning(txInfo);return retVal;}

下面重点就是看这个三个方法,准备,回滚,提交。
首先先明确事务这个东西,就是要不执行,要么都不执行。是connect实现的。报错时,调用connect的回滚方法;没有异常的时候。调用connect的提交方法。java中操作事务就是根据不同的情况调用connect的不同的方法。但是一个connect中有正在实行的事务,是不能在创建新事物的,只能重新创建一个connect,这也是事务传播行为的逻辑操作。


准备:
TransactionAspectSupport#createTransactionIfNecessary

 protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {// 这个变成了个委托类,并赋值了名称,这里的名称就是注解标注的方法全类名if (txAttr != null && txAttr.getName() == null) {txAttr = new DelegatingTransactionAttribute(txAttr) {@Overridepublic String getName() {return joinpointIdentification;}};}TransactionStatus status = null;if (txAttr != null) {if (tm != null) {// 创建事务status = tm.getTransaction(txAttr);}else {if (logger.isDebugEnabled()) {logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +"] because no transaction manager has been configured");}}}// 封装事务信息。return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);}

AbstractPlatformTransactionManager#getTransaction
这个方法太多的条件判断,分开来说

Object transaction = doGetTransaction();

得到事务对象
org.springframework.jdbc.datasource.DataSourceTransactionManager#doGetTransaction

 @Overrideprotected Object doGetTransaction() {DataSourceTransactionObject txObject = new DataSourceTransactionObject();txObject.setSavepointAllowed(isNestedTransactionAllowed());ConnectionHolder conHolder =(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());txObject.setConnectionHolder(conHolder, false);return txObject;}

创建了个事务封装对象,分析下DataSourceTransactionObject ,继承JdbcTransactionObjectSupport,

 // 是否是新的连接private boolean newConnectionHolder;// 是否重置自动提交private boolean mustRestoreAutoCommit;

JdbcTransactionObjectSupport中属性,基本上都是事务相关属性。

 // 保存connect连接的private ConnectionHolder connectionHolder;// 隔离级别private Integer previousIsolationLevel;// 只读事务private boolean readOnly = false;// 是否支持保存点private boolean savepointAllowed = false;

这里是从数据库连接池中得到连接并封装为ConnectionHolder

ConnectionHolder conHolder =(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());

看下getResource这个方法,这个以后要经常用

 public static Object getResource(Object key) {// 得到一个key,事务的逻辑是返回的就是番薯key,没有进入到条件块中Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);Object value = doGetResource(actualKey);if (value != null && logger.isTraceEnabled()) {logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" +Thread.currentThread().getName() + "]");}return value;}

doGetResource方法就是取出当前线程中保存的值。记住,第一次创建的时候返回的是null,没有往里面放值呢。

 private static Object doGetResource(Object actualKey) {// resources是一个ThreadLocal,用来保存当前线程的数据。Map<Object, Object> map = resources.get();if (map == null) {return null;}// 通过key得到值Object value = map.get(actualKey);// Transparently remove ResourceHolder that was marked as void...if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {map.remove(actualKey);// Remove entire ThreadLocal if empty...if (map.isEmpty()) {resources.remove();}value = null;}return value;}

txObject.setConnectionHolder(conHolder, false);

这点也重要,类似从缓存中找ConnectionHolder,并设置给事务对象,这里的第二个参数是:是否是仙剑的连接,这里设置的是false。

到此为止,事务的封装对象就介绍完了,核心是ConnectionHolder。记住,此时的事务对象的连接是null。


继续分析getTransaction方法。下面有事务传播行为的逻辑了,首先要搞懂事务传播行为是什么。。

  • TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。

  • TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。

  • TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。

  • TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。

  • TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。

  • TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。

先走一遍事务的逻辑,一开始是没有事务的,所以存在事务的情况之后再分析;

     // 这里有个特殊的,就是强依赖事务的,没有就抛异常。if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {throw new IllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'");}// 这三个有个共同的特点,就是在没有事务的情况下,都会创建新的事务else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {SuspendedResourcesHolder suspendedResources = suspend(null);if (debugEnabled) {logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);}try {return startTransaction(def, transaction, debugEnabled, suspendedResources);}catch (RuntimeException | Error ex) {resume(null, suspendedResources);throw ex;}}else {// 剩下的就是以非事务的方式运行。if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {logger.warn("Custom isolation level specified but no actual transaction initiated; " +"isolation level will effectively be ignored: " + def);}boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);}

先分析创建事务的

 else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {//挂起事务的逻辑,因为目前还没有事务,所以传入的参数是nullSuspendedResourcesHolder suspendedResources = suspend(null);if (debugEnabled) {logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);}try {// 开始事务,准确的来说是给connect设置参数return startTransaction(def, transaction, debugEnabled, suspendedResources);}catch (RuntimeException | Error ex) {resume(null, suspendedResources);throw ex;}}

先看挂起事务的逻辑吧
org.springframework.transaction.support.AbstractPlatformTransactionManager#suspend

 protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {// 如果有事务同步器if (TransactionSynchronizationManager.isSynchronizationActive()) {// 这里是调用事务同步器的挂起List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();try {Object suspendedResources = null;// 有事务,就挂起事务,这个逻辑还挺重要的,稍后分析if (transaction != null) {suspendedResources = doSuspend(transaction);}// 下面的逻辑就是得到当前事务的各种参数,所谓备份保存在SuspendedResourcesHolder中,因为要挂起,等恢复的时候需要这些参数的。String name = TransactionSynchronizationManager.getCurrentTransactionName();TransactionSynchronizationManager.setCurrentTransactionName(null);boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();TransactionSynchronizationManager.setActualTransactionActive(false);return new SuspendedResourcesHolder(suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);}catch (RuntimeException | Error ex) {// doSuspend failed - original transaction is still active...doResumeSynchronization(suspendedSynchronizations);throw ex;}}// 如果没有事务通过器呢 ,有事务,挂起事务。else if (transaction != null) {// Transaction active but no synchronization active.Object suspendedResources = doSuspend(transaction);return new SuspendedResourcesHolder(suspendedResources);}else {// 啥样没有返回nullreturn null;}}

看下挂起事务的逻辑
org.springframework.jdbc.datasource.DataSourceTransactionManager#doSuspend

 protected Object doSuspend(Object transaction) {// 转换为事务的对象DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;// 将连接器设置为nulltxObject.setConnectionHolder(null);// 这里是解绑操作,发挥的是map中value,这里返回的是事务中ConnectionHolder,绑定,解绑操作也确保了一个线程,一个连接connectreturn TransactionSynchronizationManager.unbindResource(obtainDataSource());}

挂起操作就是将事务中的ConnectionHolder设置为null,并且返回事务中的ConnectionHolder,将其封装在SuspendedResourcesHolder对象中。由此依旧可以看出事务强依赖connect.


下面分析开始事务的逻辑
org.springframework.transaction.support.AbstractPlatformTransactionManager#startTransaction

 private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);// 封装DefaultTransactionStatus对象DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);// 这里是重头戏,设置连接的参数了doBegin(transaction, definition);// 准备同步器。prepareSynchronization(status, definition);return status;}

org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin

 protected void doBegin(Object transaction, TransactionDefinition definition) {// 转为事务对象DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;Connection con = null;try {// 如果事务没有连接,就从连接池中取出一个。if (!txObject.hasConnectionHolder() ||txObject.getConnectionHolder().isSynchronizedWithTransaction()) {Connection newCon = obtainDataSource().getConnection();if (logger.isDebugEnabled()) {logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");}// 设置为事务,注意,这里才是创建连接,参数true,表示是否新创建的连接txObject.setConnectionHolder(new ConnectionHolder(newCon), true);}// 设置通关事务参数txObject.getConnectionHolder().setSynchronizedWithTransaction(true);con = txObject.getConnectionHolder().getConnection();// 给连接设置注解中的参数值,是否是只读事务,事务的隔离级别。Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);txObject.setPreviousIsolationLevel(previousIsolationLevel);txObject.setReadOnly(definition.isReadOnly());// 连接默认是自动提交的,设立设置为false.if (con.getAutoCommit()) {txObject.setMustRestoreAutoCommit(true);if (logger.isDebugEnabled()) {logger.debug("Switching JDBC Connection [" + con + "] to manual commit");}con.setAutoCommit(false);}// 执行sql,设置为只读的事务prepareTransactionalConnection(con, definition);// 设置该事务是启动状态txObject.getConnectionHolder().setTransactionActive(true);// 设置超时时间int timeout = determineTimeout(definition);if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {txObject.getConnectionHolder().setTimeoutInSeconds(timeout);}// ,记得创建连接的参数吗,新创建的连接,绑定线程if (txObject.isNewConnectionHolder()) {TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());}}catch (Throwable ex) {if (txObject.isNewConnectionHolder()) {DataSourceUtils.releaseConnection(con, obtainDataSource());txObject.setConnectionHolder(null, false);}throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);}}

这个方法就是给连接设置参数,还有一些其他的逻辑;如果没有连接,创建连接;如果是新的连接,就绑定连接。


org.springframework.transaction.support.AbstractPlatformTransactionManager#prepareSynchronization

 protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {// 如果是新的同步器,就给TransactionSynchronizationManager设置参数。事务同步管理器中是当前事务的参数if (status.isNewSynchronization()) {TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?definition.getIsolationLevel() : null);TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());// 这里的就是绑定线程,给ThreadLocal中设置值,表示当前有事务。TransactionSynchronizationManager.initSynchronization();}}

小结:
开始事务总体逻辑,就是将注解中的属性值,给连接connect赋值;同时,事务同步器管理器中也同样赋值。
到这块就完成了,之后将事务状态的对象返回就可以了DefaultTransactionStatus。在往上走一个就是org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary方法,再次封装一层,变成了TransactionInfo;

到此有感觉spring事务做了什么了吗?本质就是进入方法之前,spring棒我们从数据库连接池中取出一个连接,然后设置好参数,放起来(绑定数据库连接值和连接holder),等我们用到连接的时候,取的是这个放好的,而不是从数据库连接池中现取的。


之前分析了创建新的事务,现在分析下在没有事务的情况下,不走事务的逻辑,即这三的逻辑。

  • TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。

  • TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。

回到org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction

     else {// Create "empty" transaction: no actual transaction, but potentially synchronization.if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {logger.warn("Custom isolation level specified but no actual transaction initiated; " +"isolation level will effectively be ignored: " + def);}boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);}

org.springframework.transaction.support.AbstractPlatformTransactionManager#prepareTransactionStatus

 protected final DefaultTransactionStatus prepareTransactionStatus(TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {// 同样是封装对象,DefaultTransactionStatus status = newTransactionStatus(definition, transaction, newTransaction, newSynchronization, debug, suspendedResources);// 准备同步prepareSynchronization(status, definition);return status;}

如果没有事务,transaction是null,但是newTransaction是true,因为之前是没有事务的,这个表示是新建的事务。同样会设置同步器参数;我理解的同步器就是保存当前事务的参数,如果是新建同步器,就要设置。

到此看没有绑定连接,也就是说用到连接的时候,自己取,spring不管。


下面分析下载存在事务的情况下,是如何处理的。
org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction

     if (isExistingTransaction(transaction)) {// Existing transaction found -> check propagation behavior to find out how to behave.return handleExistingTransaction(def, transaction, debugEnabled);}
 // 如果这个事务是有连接的,并且这个连接还启动着。。protected boolean isExistingTransaction(Object transaction) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());}

org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction

     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);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 {return startTransaction(definition, transaction, debugEnabled, suspendedResources);}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()) {// 在这里创建了保存点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.// 这是给jta使用的,不分析了return startTransaction(definition, transaction, debugEnabled, null);}}

有事务,嵌套事务使用,保存点,也就是说回滚也是回滚本方法得到。

     boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);

剩下的就是使用当前的事务了。

新建事务:startTransaction
不走事务:prepareTransactionStatus,此时的事务参数为null
使用原来的事务:prepareTransactionStatus,事务参数是原来的事务


到此事务的准备工作就完成了。之后执行目标方法,如果报错,就回滚,看看回滚的逻辑
回到org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction

         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 exceptioncompleteTransactionAfterThrowing(txInfo, ex);throw ex;}

org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing

 protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {if (txInfo != null && txInfo.getTransactionStatus() != null) {if (logger.isTraceEnabled()) {logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +"] after exception: " + ex);}// 如果是符合预期的异常,就回滚,否则的话走else,发现是直接提交了,if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {try {txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());}catch (TransactionSystemException ex2) {logger.error("Application exception overridden by rollback exception", ex);ex2.initApplicationException(ex);throw ex2;}catch (RuntimeException | Error ex2) {logger.error("Application exception overridden by rollback exception", ex);throw ex2;}}else {// We don't roll back on this exception.// Will still roll back if TransactionStatus.isRollbackOnly() is true.try {txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());}catch (TransactionSystemException ex2) {logger.error("Application exception overridden by commit exception", ex);ex2.initApplicationException(ex);throw ex2;}catch (RuntimeException | Error ex2) {logger.error("Application exception overridden by commit exception", ex);throw ex2;}}}}

直接进入org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback

 private void processRollback(DefaultTransactionStatus status, boolean unexpected) {try {boolean unexpectedRollback = unexpected;try {triggerBeforeCompletion(status);// 如果有保存点,回滚保存点if (status.hasSavepoint()) {if (status.isDebug()) {logger.debug("Rolling back transaction to savepoint");}status.rollbackToHeldSavepoint();}// 如果是新建的,回滚else if (status.isNewTransaction()) {if (status.isDebug()) {logger.debug("Initiating transaction rollback");}doRollback(status);}else {// Participating in larger transactionif (status.hasTransaction()) {if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {if (status.isDebug()) {logger.debug("Participating transaction failed - marking existing transaction as rollback-only");}doSetRollbackOnly(status);}else {if (status.isDebug()) {logger.debug("Participating transaction failed - letting transaction originator decide on rollback");}}}else {logger.debug("Should roll back transaction but cannot - no transaction available");}// Unexpected rollback only matters here if we're asked to fail earlyif (!isFailEarlyOnGlobalRollbackOnly()) {unexpectedRollback = false;}}}catch (RuntimeException | Error ex) {triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);throw ex;}triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);// Raise UnexpectedRollbackException if we had a global rollback-only markerif (unexpectedRollback) {throw new UnexpectedRollbackException("Transaction rolled back because it has been marked as rollback-only");}}finally {cleanupAfterCompletion(status);}}

回滚有保存点的,如果是新建的事务,直接回滚**,如果是复用事务的,啥也没做。。**
重点看下cleanupAfterCompletion,这里面做了很多工作

 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");}Object transaction = (status.hasTransaction() ? status.getTransaction() : null);resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());}}

回滚操作其实很简单,就是当调用connect的回滚方法。


看完回滚操作,看下提交的操作。

org.springframework.transaction.support.AbstractPlatformTransactionManager#commit
提交时候还有回滚操作,这块还没整明白。部分回滚?

 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, false);return;}if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {if (defStatus.isDebug()) {logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");}processRollback(defStatus, true);return;}processCommit(defStatus);}

总体分析完了,东西是有点多,后面打算看看mybatis的事务和spring事务的联系。如果不用spring的事务,mybatis是如何处理的呢?

总结:
事务这块主要有两个主要的类:
事务管理器;创建事务的,
事务同步管理器:管理connectHolder的,同时保存各个线程中事务的信息。

dobegin方法是设置connect的,同时将注解中的信息设置给connect;
prepareSynchronization方式是设置通过器的,就是说保存当前的事务信息。

事务的传播行为其实就是几种情况:
有事务:
不支持的报错;
不用事务:挂起事务,非事务方式运行;
新建一个:挂起事务,自己新建一个;
用这个事务;

没有事务:
新建一个事务;
或者非事务方式运行。

无论怎么样,只要设置了@transactional注解,就会有一个事务对象。事务的中的连接信息是沿用旧的,还自己自己新建,还是就不用事务;三种;而事务同步,只有事务同步器是新建的,同时之前没有同步器,才会设置事务的信息;

【Spring-tx】事务逻辑相关推荐

  1. springaop事务逻辑原理_太狠了!阿里大牛手写的Spring核心面试笔记:IOC+AOP+MVC+事务...

    Spring作为现在最流行的java 开发技术,其内部源码设计非常优秀.如果你不会Spring,那么很可能面试官会让你回家等通知. Spring是什么? 有一个工地,几百号人在用铁锹铲子挖坑. 如果开 ...

  2. springaop事务逻辑原理_架构师:一篇文章掌握——Spring 事务管理

    对大多数Java开发者来说,Spring事务管理是Spring应用中最常用的功能,使用也比较简单.本文主要逐步介绍Spring事务管理的相关知识点及原理,作为Spring事务管理的学习总结. 一.关键 ...

  3. spring tx:advice 和 aop:config 配置事务

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010741376/article/details/46584463 spring tx:advic ...

  4. 解决在Spring整合Hibernate配置tx事务管理器出现错误的问题

    解决在Spring整合Hibernate配置tx事务管理器出现错误的问题 参考文章: (1)解决在Spring整合Hibernate配置tx事务管理器出现错误的问题 (2)https://www.cn ...

  5. Spring Tx (一) (事务)

    文章目录 1.事务的定义 2.事务特性 3.事务的属性 3.1 隔离级别 3.2 传播机制 1.事务的定义 应用层: Spring-Mybatis 驱动层: JDBC事务单数据库事务, JTA事务分布 ...

  6. Spring研究笔记------事务探究

    2019独角兽企业重金招聘Python工程师标准>>> 最近看了比较多Spring的东西,脑中概念知识比较杂乱,借助周六周天的闲暇时间,写一些内容,梳理一下自己脑中的概念,也以此作为 ...

  7. Spring分布式事务实现

    分布式事务是指操作多个数据库之间的事务,spring的org.springframework.transaction.jta.JtaTransactionManager,提供了分布式事务支持.如果使用 ...

  8. spring教程--事务管理

    Spring的事务管理 1.1 事务: 事务:是逻辑上一组操作,要么全都成功,要么全都失败. 事务特性: ACID: 原子性:事务不可分割 一致性:事务执行的前后,数据完整性保持一致. 隔离性:一个事 ...

  9. Spring TX源码分析

    一.先思考一下 什么是事务? 事务是一系列数据库操作的集合,在一个事务里,所有有关的数据库操作一起提交或一起回滚 事务用在什么地方? 如果多个数据库操作需要一起生效或一起失效,那么这些操作需要放在一个 ...

  10. batch spring 重复执行_一个3年老javaer竟然连Spring的事务管理都不知道,惊呆了

    1.事务介绍 事务(Transaction),一般是指要做的或所做的事情.在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit). 这里我们以取钱的例子来讲解:比如你去ATM ...

最新文章

  1. 好用的 Markdown 编辑器 Typora【Window 、Linux 下的安装教程】
  2. 腾讯云张贤国:北大将我从少年变成了技术研究者
  3. IOS14.3开发之使用纯代码创建UIButton以及弹框的使用
  4. mysql数据库设计三大范式_数据库设计三大范式详解
  5. lptv自建服务器,如何搭建自己的IPTV平台
  6. 华为智慧屏鸿蒙挂安卓9,荣耀先行!华为智慧屏9月发布:搭鸿蒙系统和自研芯片...
  7. 应用计算机技术建立起来的地图,地理信息系统的思考题及其答案
  8. html表白代码大全_100条代码,拿去“表白”
  9. 一级计算机基础试题答案,计算机一级计算机基础试题及答案
  10. 数据中心监控软件 - ManageEngine OpManager
  11. 优质短信api接口具备的特点
  12. 【业务知识】金融、银行业务知识点(转载)
  13. Python堆糖网图片爬虫,多进程及多线程的使用例子
  14. 施一公 - 清华讲座
  15. 搭建简单windows版NAS
  16. 苹果系统安全吗?7种方法保护自己的隐私
  17. Unity3D中使用Leap Motion进行手势控制
  18. Joel谈优秀软件开发-摘录
  19. eps提取高程点在哪里_只需一个命令,就能提取CAD图纸所有高程点坐标,感觉学费白交了...
  20. 网络数据传输的封装总结

热门文章

  1. php面向对象代码_PHP 面向对象实现代码
  2. 翻译:如何理解K-means的缺点
  3. 算法:二分法求平方根Sqrt(x)
  4. 极客大学架构师训练营 架构师职责 听课总结 -- 第一课
  5. Ubiquant LGBM Baseline 九坤量化大赛 版本44
  6. Some of the operators in the model are not supported by the standard TensorFlow Lite runtime.
  7. 32 开漏输出 高电平_MCU输入输出端口设置
  8. python socket recvfrom 超时捕获_python-udp客户端超时机制
  9. 如何提高阅读源代码的效率
  10. 大牛学习爬虫经验,转自知乎