上篇咱们分享了Spring AOP的相关源码,今天咱们分享一个和Spring AOP联系很是紧密的话题---Spring事务。不少人认为事务很简单,可是每每在工做中遇到一些事务的坑(尤为是事务方法中嵌套其它事务方法一块儿使用时)以后,咱们殊不知道问题产生的缘由和如何有效的解决。这就须要去分析Spring的核心源码,最终踏实地找到问题的缘由和解决思路。spring
先来看Spring事务的底层运行流程编程
1、事务配置相关
TransactionManagementConfigurationSelector:配置启动事务启动(EnableTransactionManagement)时,导入注册的配置bean。它包括AutoProxyRegistrar和ProxyTransactionManagementConfiguration两大配置块。
AutoProxyRegistrar:负责依赖注入事务的相关属性配置和注入事务入口类(InfrastructureAdvisorAutoProxyCreator类);
ProxyTransactionManagementConfiguration:负责注入事务相关的Bean, 包括:事务切面Bean(BeanFactoryTransactionAttributeSourceAdvisor)、TransactionAttributeSource(事务配置属性bean)和TransactionInterceptor(事务拦截器bean)等;
2、事务运行拦截相关
AopProxy:Spring AOP 动态代理的基接口,负责定义Proxy的基础行为;
MethodInterceptor:Spring AOP调用链中拦截器的内部核心接口,全部类型的切面最终都会最终包装成此接口触发统一拦截;
TransactionInterceptor:Spring事务拦截器的核心业务实现,AOP调用链也最终触发它的invoke方法;
TransactionManager:Spring管理的基接口,做为子接口上层接口区分,并无定义实际的事务行为能力;
PlatformTransactionManager:继承TransactionManager,定义事务和基础行为;
AbstractPlatformTransactionManager:负责实现整个事务管理和运行过程当中的公共行为和通用实现逻辑,它继承至PlatformTransactionManager接口;缓存
接下来咱们来分块分析一下,Spring事务的源码,其中的一些坑和重要结论会在这个过程分享。
1、事务配置
TransactionManagementConfigurationSelector.selectImports()负责定义外部加入spring容器的配置类
此方法最终在ConfigurationClassParser中被解析并最终实例化为bean
AutoProxyRegistrar.registerBeanDefinitions()把InfrastructureAdvisorAutoProxyCreator注册beandefinition
ProxyTransactionManagementConfiguration.transactionAdvisor()注入事务切面ide
2、事务建立
实际运行入口之一(还有cglib):JdkDynamicAopProxy..invoke()
ReflectiveMethodInvocation.proceed()切面调用链处理核心方法
TransactionInterceptor.invoke()从这里触发事务拦截
TransactionAspectSupport.invokeWithinTransaction()实现Spring事务的核心业务
TransactionAspectSupport.determineTransactionManager()定义指定的事务管理器
对于事务管理器,默认使用DataSourceTransactionManager(可配置数据源的事务管理器),也可自定义事务管理器,而后配置数据源便可。
createTransactionIfNecessary()建立事务信息TransactionInfo:其中包括数据源、事务链接(ConnectionHolder)、事务状态、链接缓存等;
DataSourceTransactionManager.doGetTransaction()获取事务对象:里面包含链接包装和缓存
TransactionSynchronizationManager.getResource()链接线程级缓存:确保当前线程拿到惟一的数据链接
AbstractPlatformTransactionManager.startTransaction()开启一个新事务
只有newTransaction为true时,spring才会作实际的提交或回滚,这里是一个很重要的点。不少嵌套事务的坑,都是这里没有理解清楚。
DataSourceTransactionManager.doBegin()开启事务核心源码
TransactionSynchronizationManager.bindResource()设置当前链接和数据源的线程级绑定
3、事务回滚
对于非编程式事务而言,Spring事务的核心实现其实就是用try / catch 包裹事务提交和回滚的范式而已,但提交和回滚里面的包装大有讲究。
TransactionAspectSupport.completeTransactionAfterThrowing()事务回滚实现
以上截图中doSetRollbackOnly(),不会在链接上实际设置回滚点,只打个标记(当前事务须要回滚, commit时会使用该标记)!源码分析
4、事务提交
AbstractPlatformTransactionManager.commit()事务实际提交源码这里
cleanupAfterCompletion()回收链接或恢复事务,这个点回味无穷:当事务传播属性为Require_New时,会暂时挂起以前的链接,而后建立新链接;当新链接提交或回滚后,经过这个方法恢复以前链接和状态!!!!ui
OK事务到这里,我根据源码分享一些关于嵌套子事务的甜点:线程
今天的Spring事务源码就暂时分享到这里,事务这块只有一层的事务很简单,但当嵌套了多个(层)子事务(并且每一个子事务的事务传播属性可能不同的状况下)时就当另当别论了。须要咱们根据源码的规律去分析每层子事务该如何流转!!因此须要把这块的源码搞熟,遇到复杂的嵌套事务分析缘由,那问题就不大了。更新spring源码的干货请继续关注。3d