Spring事务及源码解读

spring事务7种传播特性(实质就是数据库连接的相关操作)

        PROPAGATION_REQUIRED:如果当前事务不存在则新建一个事务,如果已经存在则使用已存在的事务 

        PROPAGATION_REQUIRES_NEW:如果当前事务存在则挂起当前事务,然后新建一个事务

        PROPAGATION_NESTED:嵌套事务,如果当前事务存在,则使用嵌套事务,如果不存在,则新建一个事务

        PROPAGATION_MANDATORY:支持事务,如果没有事务则抛出异常

        PROPAGATION_NOT_SUPPORTED:不支持事务,如果当前存在事务则将事务挂起

        PROPAGATION_NEVER:以非持事务方式执行,如果当前存在事务则抛出异常

        PROPAGATION_SUPPORTS:如果事务存在则使用当前事务执行,如果事务不存在则以非事务方式执行


spring事务源码解析

        1)spring事务入口方法org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction

        2)每次进入事务调用的时候需要判断是否需要创建事务,所以进入方法org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary

        3)进入获取事务方法org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction,在这个方法中会根据当前事务的传播行为进行事务获取,

        4)获取已经存在的事务信息(其实就是获取数据库连接),org.springframework.jdbc.datasource.DataSourceTransactionManager#doGetTransaction

        5)第一次进入方法时isExistingTransaction(transaction)肯定为false,则走创建新事物代码逻辑

        6)核心,真正开启一个事务的地方,其实也就是获取一个数据连接,并没有什么特别的地方。org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin

        将数据库连接信息和上面说的resource绑定

        7)到这里的时候,已经创建了一个事务(本质就是已经创建了一个数据库连接),最终我们得到的是一个TransactionInfo 对象,所有需要的信息在这里都可以拿的到。拿到事务信息之后就可以进行业务处理了,这里我们业务处理就不讲解了,主要讲下事务回滚和事务提交

        事务提交,主要方法入口org.springframework.transaction.interceptor.TransactionAspectSupport#commitTransactionAfterReturning

        txInfo.getTransactionManager().commit()方法调用入口org.springframework.transaction.support.AbstractPlatformTransactionManager#commit


        事务真正提交,只有newTransaction为true时才会真正提交事务信息,到这里一个完整的事务已经处理完成了。org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommit

        事务回滚和事务提交一样,也是拿到数据连接进行回滚,这里就不做说明了,看源码很同意明白,不过值得一提的是,同样只有newTransaction为true时才会真正执行回滚操作

        8)上面说的是一个完整的事务的执行过程(未涉及到事务传播行为),现在我们来说说事务的传播行为是如何实现的,且不同的传播属性是如何实现的,这里只分析,PROPAGATION_REQUIRED, PROPAGATION_REQUIRES_NEW,PROPAGATION_REQUIRES_NEW三种传播行为。在事务传播行为中,再次进入getTransaction方法中的doGetTransaction会获取到上次存储的数据库连接信息,如果已经存在事务了则走下面的这个分支

        9)为现有事务创建一个TransactionStatus。这个方法里面会为不同的传播行为执行不同的逻辑,这里我们先看下如果传播行为是PROPAGATION_REQUIRED代码是如何实现的,注意这里的newTransaction为false。org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction

        10)上面方法中只是通过给定的参数获取一个TransactionStatus对象,同时将对象的newTransaction状态改为false,这里并没有重新去创建数据库连接,而是使用原有的数据库连接。紧接着执行的流程和第 7)是一样了。

        11)上面第 8)到 10)分析了PROPAGATION_REQUIRED的事务传播行为,接着我们分析PROPAGATION_REQUIRES_NEW的传播行为,首先入口逻辑和第 8)是一样的,只是具体这里面执行逻辑不同,这里是先将原有的事务挂起,然后在创建一个新的事务(新的数据库连接),除了挂起事务后,其他和第5)到第 6)的逻辑是一样的。

        12)上面 11)分析了PROPAGATION_REQUIRES_NEW事务传播行为,紧接着分析PROPAGATION_NESTED的传播行为,这里其实也没有很特别的东西,也只是使用原来的事务,然后在原来事务基础上创建了保存点,紧接着执行的流程和第 7)是一样了。从这里可以看出为什么嵌套事务在回滚时不会影响外部的事务,而外部事务的回滚会影响内部事务了,嵌套事务的回滚仅仅是回滚到某一个保存点,而外层事务回滚是回滚整个事务。

上面是我对事务源码的一个简单的分析记录

transactional失效问题解析

        1). 如果方法执行过程中抛出了Execption异常,即使加了@transactional注解,程序也不会按你预期的结果执行,事务默认支持RuntimeExecption和Error(Spring会对unchecked异常进行事务回滚;如果是checked异常则不回滚),如果想要支持Execption异常可以通过@transactional中的rollbackFor进行处理,源码解析如下


说明:这些仅仅是自己在学习过程中的一些心得体会和笔记,方便后续查看和复习,学习参考可能来自网上也可能来自书本,如有侵权,请联系删除。

你可能感兴趣的:(Spring事务及源码解读)