Spring 中的声明式事务处理是用户最常用的,通过将事务处理的过程和业务代码分离开来,大大简化了代码的编写。声明式事务有两种使用方式,第一种是纯粹的 xml 文件配置:
在这里配置了数据源 dataSource、事务管理器 transactionManager、待事务增强的目标业务 Bean、事务增强配置。第二种是注解方式,不过 xml 中依然需要配置数据源 dataSource 和事务管理器 transactionManager,额外还需要加上 annotation-driven 配置。
分析流程入口:TxNamespaceHandler
1.解析advice
2.解析 <tx:annotation-driven/>标签
3.获取mode,如果为aspectj,就提供对aspectj方式进行事务切入的支持;如果不是aspectj,就配置自动代理创建器
4.对于aspectJ,registerTransactionAspect创建出RootBeanDefinition,并且注入属性,最后把这个组件注册到parserContext中
5.对于configureAutoProxyCreator,首先注册自动代理创建器,创建RootBeanDefinition
6.创建TransactionInterceptor的BeanDefinition
7. registerTransactionManager(element, interceptorDef); 创建好的事务管理器,进行注册
8.为TransactionInterceptor织入AnnotationTransactionAttributeSource
9.为BeanFactoryTransactionAttributeSourceAdvisor织入AnnotationTransactionAttributeSource
10.为BeanFactoryTransactionAttributeSourceAdvisor织入TransactionInterceptor
11.Spring会保证所有bean在实例化的时候都会调用其postProcessAfterInitialization方法,我们可以使用这个方法包装和改变bean,而真正实现这个方法是在其父类AbstractAutoProxyCreator类中:
12.还是同aop分析,获取bean匹配的增强器,然后调用createProxy创建代理
13.获取事务的属性,然后把解析好的事务属性存入缓存
13.1 查看方法中获取是否存在事务声明
13.2 查看方法所在类中是否存在事务声明
13.3 查看接口方法中是否存在事务声明
13.4 查看接口类中是否存在事务声明
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2.申明式事务
申明式事务整体调用过程,可以抽出2条线:
1.使用代理模式,生成代理增强类。
2.根据代理事务管理配置类,配置事务的织入,在业务方法前后进行环绕增强,增加一些事务的相关操作。例如获取事务属性、提交事务、回滚事务。
代理模式:AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
最终调用的是:registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);基础构建增强自动代理构造器
核心方法:transactionAdvisor()事务织入
定义了一个advisor,设置事务属性、设置事务拦截器TransactionInterceptor、设置顺序。核心就是事务拦截器TransactionInterceptor。
TransactionInterceptor使用通用的spring事务基础架构实现“声明式事务”,继承自TransactionAspectSupport类(该类包含与Spring的底层事务API的集成),实现了MethodInterceptor接口
这里有几个核心方法:挂起当前事务suspend()、开启新事务doBegin()。
如上图,开启新事务的准备工作doBegin()的核心操作就是:
1.DataSourceTransactionObject“数据源事务对象”,设置ConnectionHolder,再给ConnectionHolder设置各种属性:自动提交、超时、事务开启、隔离级别。
2.给当前线程绑定一个线程本地变量,key=DataSource数据源 v=ConnectionHolder数据库连接。
如上图,各种判断:
- 1.如果事务明确标记为本地回滚,-》执行回滚
- 2.如果不需要全局回滚时提交 且 全局回滚-》执行回滚
- 3.提交事务,核心方法processCommit()