入口
我们还是先从入口说起,TransactionAutoConfiguration是一个EnableAutoConfiguration类跟随着spring boot启动被加载进来,从这里我们可以看得出Spring Boot默认会启动EnableTransactionManagement打开事务支持。
接下来我们来看下EnableTransactionManagement这个注解,跟Spring Boot其他EnableXXX注解一样都@Import了一个ImportSelector类来完成事务的初始化。
TransactionManagementConfigurationSelector引入两个Bean:
- AutoProxyRegistrar:// TODO : 后面AOP原理解析再补充
- ProxyTransactionManagementConfiguration:核心配置
这里实例化了3个对象:
- BeanFactoryTransactionAttributeSourceAdvisor:事务切面,aop拦截后交由TransactionInterceptor处理
- TransactionAttributeSource:@Transactional注解处理
- TransactionInterceptor:事务拦截器,Spring的拦截器(事务核心处理方法)
整个事务管理基于AOP机制进行,通过织入拦截点对方法进行拦截,然后委托给TransactionInterceptor进行处理,如下图所示:
BeanFactoryTransactionAttributeSourceAdvisor
通过CglibAopProxy的内部类ProxyCallbackFilter来获取切面,这个不做重点讲,主要就是利用了Spring AOP机制来实现切面通知
TransactionAttributeSource
这个类的职责比较简单就是利用SpringTransactionAnnotationParser解析器来判断拦截的方法是否带有@Transactional注解,若有则解析出里面的属性拼装成一个TransactionAttribute并返回
TransactionInterceptor
这个拦截器是Spring 事务管理的核心,我们这个章节将着重讲讲这个拦截器。拦截器核心方法为invoke通过动态代理的方式调用该方法,然后委托给TransactionAspectSupport这个子类的invokeWithinTransaction进行处理
事务核心处理逻辑分为3种情况:
- Reactive事务管理,这个是响应式编程的一部分,具体感兴趣读者可以webflux相关资料
- 普通的事务管理,这个是我们的核心,大部分请求使用的即是该逻辑,我们具体讲这部分逻辑
- 回调式事务管理,这种可以参考TransactionTemplate的使用方法
主体逻辑也是十分简单,主要就是开启事务,执行方法,然后根据异常情况commit或者rollback
这里事务的TransactionManager默认使用的是JdbcTransactionManager,开启事务的过程比较简单,就是新建一个事务然后把事务搬到当前线程中就行createTransactionIfNecessary->prepareTransactionInfo->bindToThread,然后使用动态代理的方式执行方法调用proceedWithInvocation,执行结束后根据情况提交或者回滚事务completeTransactionAfterThrowing、commitTransactionAfterReturning,这里稍微讲下cleanupTransactionInfo这个方法回去调用TransactionInfo中的restoreThreadLocalStatus,我们可以看到这个方法是将线程变量设置为老的那个transactionInfo,这里为啥要这样做呢,我的理解应该是为了实现事务隔离,比如内嵌事务这种场景。
在上上面那个代码块里面还使用了VavrDelegate,点击查看Vavr库
事务传播机制
事务传播级别位于TransactionDefinition进行定义,如下图:(载自这篇文章)
- PROPAGATION_xx : Spring事务传播级别
- PROPAGATION_REQUIRED:如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。(默认)
- PROPAGATION_SUPPORTS:如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
- PROPAGATION_MANDATORY:如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常
- PROPAGATION_REQUIRES_NEW:总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起
- PROPAGATION_NOT_SUPPORTED:总是非事务地执行,并挂起任何存在的事务
- PROPAGATION_NEVER:总是非事务地执行,如果存在一个活动事务,则抛出异常
- PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, PROPAGATION_REQUIRED 属性执行
- ISOLATION_xx: 数据库隔离级别
- ISOLATION_READ_UNCOMMITTED:读未提交
- ISOLATION_READ_COMMITTED :读提交(mysql默认)
- ISOLATION_REPEATABLE_READ :重复读(推荐使用,避免间隙锁)
- ISOLATION_SERIALIZABLE :串行化(性能低)
TransactionalEventListener事务监控使用说明
TODO