Spring 事务机制实现原理

154 阅读4分钟

前言

最近面试被频繁问到的一个问题就是,Spring的事务是如何实现的,如果让你自己去实现一个事物的方式,你应该怎么做呢? 在我们学习Spring的时候,我们都知道Spring Aop切面编程是实现本地事务的关键,说到Aop我们都知道是通过代理的方式,那么具体Spring是如何通过代理的方式来实现事务的我们通过这边篇技术分享来一起探索下,如果有说的不对的地方,希望朋友们指出🙏

Spring提供的事务注解

Spring提供的事务注解有@Transactional、@EnableTransactionManagement 通常情况下我们会通过@Transactional注解来去在我们需要加入事务的方法上去定义。

84BB450D-5761-4254-95EB-4901DF292A93.png

@Transactional

下面我们来看下具体参数代表的意思

Propagation(事务的传播特性):

分别有这几种 REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。

MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。

REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。

NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

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

NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。

timeout(事务超时时间)

默认30秒

isolation(事务的隔离级别)

Isolation.READ_UNCOMMITTED : 读取未提交数据(会出现脏读, 不可重复读) 基本不使用 Isolation.READ_COMMITTED : 读取已提交数据(会出现不可重复读和幻读) Isolation.REPEATABLE_READ:可重复读(会出现幻读) Isolation.SERIALIZABLE:串行化

readOnly(事务是否为只读事务)

True表示只读,默认是false可读写。

rollbackFor(异常回滚的数组)

指定单一异常回滚:@Transactional(rollbackFor=RuntimeException.class) 指定多个异常回滚:@Transactional(rollbackFor={RuntimeException.class, Exception.class})

rollbackForClassName(异常回滚的名称数组)

指定单一异常回滚:@Transactional(rollbackForClassName =’RuntimeException‘) 指定多个异常回滚:@Transactional(rollbackForClassName ={’RuntimeException‘, ‘Exception.class’})

noRollbackForClassName(不需要回滚的异常名称数组)

noRollbackFor(不需要回滚的异常类数组)

@EnableTransactionManagement

这个注解是开启注解式事务,proxyTargetClass用来表示使用JDK的动态代理还是使用CGLIB的,AdviceMode这里的枚举类分为proxy和aspect两种,这两种是现实Aop的方式,order属性表示顺序,主要是配置一些属性。

20D759E8-360D-4AD2-8C23-48F5A96B969C.png 这里还有Import进去一个TransactionManangementConfigurationSelector类,主要的逻辑就是根据代理模式,来注册不同的BeanDefinition。

AutoProxyRegistrar和ProxyTransactionManagementConfiguration。

254D8D23-BF3C-44F6-980A-CCE6CB09E96B.png

AutoProxyRegistrar

是向容器来注册Bean的,在proxy类型下会调用AopConfigUtils.registerAutoProxyCreatorIfNecessary方法向容器中注册,主要是通过InfrastructureAdvisorAutoProxyCreator这个类,这个类的父类就是AbstractAutoProxyCreator,这里主要是完成我们aop的第一步代理的。

5045C7F1-4EF7-4591-8037-5ECF9C652A67.png

B996B9F7-3F58-4782-AE33-9F024C1B3FE4.png

ProxyTransactionManagementConfiguration

接下来我们看这个类的实现,看到Configuration我们就知道这是个配置类,主要对BeanFactoryTransactionAttributeSourceAdvisor、TransactionAttributeSource、TransactionInterceptor 还有继承的父类TransactionalEventListenerFactory这几个类进行配置。

0B98F96F-8EA6-474E-AACF-D23EC682468B.png

BeanFactoryTransactionAttributeSourceAdvisor

通过配置类的名称可以看到有Advisor,那么应该离不开Pointcut,Pointcut作为一个注解也是用来找到被代理的类,Pointcut的主要实现是依赖于TransactionAttributeSourcePointcut抽象类主要是通过matches、filter方法来匹配代理类。

7D1FEEB0-632C-40CE-85AE-C1C86C6F5158.png

TransactionAttributeSource

这个方法从上面的代码截图可以看到,retrun了一个AnnotationTransactionAttributeSource,这个正是我们常用事务的注解@Transactional的实现类, @Transactional是通过注解的方式标记在方法上面的,所以所有的事务属性都标记在@Transactional注解。

TransactionInterceptor

通过TransactionInterceptor的invoke方法找到invokeWithinTransaction,这个方法是事务拦截器的入口,主要关键的方法为determineTransactionManager—>completeTransactionAfterThrowing

58114E81-9304-4BDC-A8B1-A97317A9B08B.png E3F1ACAB-9037-429B-8A60-37EB4CD4E2D5.png

completeTransactionAfterThrowing

3BC37D56-6B94-4DC1-8C41-222B2F759ECD.png 主要依次是rollbackon判断事物是否需要回滚—>通过PlatformTransactionManager事务管理器回滚事-->通过PlatformTransactionManager事务管理器提交事务

总结

到此我们就可以知道事务主要是由PlatformTransactionManager事务管理器、TransactionDefinition事务的属性定义、TransactionStatus事务的状态这几个核心部分组成,Spring Aop事务这一块还是相对复杂的,我只是分析了部分源码,可能由于现阶段理解能力有限,后续我也会继续学习,往更加深层次的地方研究。