Spring 事务——源码分析
【事务环境搭建工作】:链接
注解 @EnableTransactionManagement:在配置类中添加注解@EnableTransactionManagement,便开启了事务功能。此注解也是了解Spring事务源码的入口。
@EnableTransactionManagement
public class TxConfig {
【1】@EnableTransactionManagement 利用 TransactionManagementConfigurationSelector 给容器中导入组件:如下代码所示,SelectorImposrts共导入了两个组件:①、AutoProxyRegistrar、②、ProxyTransactionManagementConfiguration
// xxxSelector 继承自 ImportSelector 表示给容器中导入组件
@Import({TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {......} //进入TransactionManagementConfigurationSelector的selectImports方法,发现导入两个组件
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
protected String[] selectImports(AdviceMode adviceMode) {
switch(null.$SwitchMap$org$springframework$context$annotation$AdviceMode[adviceMode.ordinal()]) {
case 1:
//导入的两个组件:AutoProxyRegistrar、ProxyTransactionManagementConfiguration
return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
}
}
【2】组件一:AutoProxyRegistrar 给容器中注册了一个 InfrastructureAdvisorAutoProxyCreator 组件。该组件继承自xxxAwareBeanPostProcessor后置处理器,利用后置处理器机制在对象创建以后进行包装,返回一个代理对象(有增强器),代理对象通过拦截器链进行调用。
//通过继承类《BeanDefinitionRegister》可以猜到该类的功能,主要是给容器中注册Bean的属性
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//......
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
}
} //进入上面的registerxxx方法:创建一个自动代理创建器
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, (Object)null);
} //进入上面registerxxx 发现它给容器中注册了一个 InfrastructureAdvisorAutoProxyCreator 组件
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
【3】ProxyTransactionManagementConfiguration 是一个配置类,如下:
第一步:给容器中注册事务增强器:1)、主要用于对事务注解 @Transactional 中的属性进行解析。给容器中注入:AnnotationTransactionAttributeSource 实例。
@Configuration(
proxyBeanMethods = false
)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
//注册事务增强器
@Bean(
name = {"org.springframework.transaction.config.internalTransactionAdvisor"}
)
@Role(2)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
//设置一个事务属性
advisor.setTransactionAttributeSource(transactionAttributeSource);
//设置一个事务拦截器
advisor.setAdvice(transactionInterceptor);
if(this.enableTx != null) {
advisor.setOrder(((Integer)this.enableTx.getNumber("order")).intValue());
} return advisor;
} //事务属性源码展示:也是一个bean,注入到容器中
@Bean
@Role(2)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
} //注入的bean对象源码展示:主要功能使用注解解析器对事务注解进行解析 publicMethodsOnly=true
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
this.annotationParsers = new LinkedHashSet(4);
//事务注解解析器
this.annotationParsers.add(new SpringTransactionAnnotationParser());
if(jta12Present) {
this.annotationParsers.add(new JtaTransactionAnnotationParser());
} if(ejb3Present) {
this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
}
}
} //进入事务注解解析器 SpringTransactionAnnotationParser 中的parseTransactionAnnotation方法
//里面的都是都是可以在@Transactional中配置的属性
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
Propagation propagation = (Propagation)attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());
Isolation isolation = (Isolation)attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
rbta.setTimeout(attributes.getNumber("timeout").intValue());
rbta.setReadOnly(attributes.getBoolean("readOnly"));
rbta.setQualifier(attributes.getString("value"));
List<RollbackRuleAttribute> rollbackRules = new ArrayList();
Class[] var6 = attributes.getClassArray("rollbackFor");
int var7 = var6.length;
//......
}
2)、事务拦截器 :TransactionInterceptor 继承自 MethodInterceptor【方法拦截器:目前给容器中放置了一个代理对象,代理对象要执行目标方法时,方法拦截器就进行工作】 ,保存了事务属性信息和事务管理器;在目标方法执行的时候,代理对象会执行拦截器链【TransactionInterceptor 】,TransactionInterceptor(事务拦截器) 的作用:①、获取事务相关属性;②、获取平台事务管理器【platformTransactionManager 】获取方式:首先会根据 Transaction 中定义的 Qualifier 属性获取事务管理器,如果未定义则根据 TransactionManagerBeanName 获取,如果事先没有指定,则根据自动装配的值获取,如果没有指定,最终会从容器中按照类型获取一个 PlatformTransactionManager;③、开启事务、执行目标方法、如果发生异常,利用事务管理器回滚操作。如果正常,则利用事务管理器提交事务。
//继承了方法拦截器
public class TransactionInterceptor extends TransactionAspectSupport
implements MethodInterceptor, Serializable { //拦截器工作通过调用invoke进行触发。
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = invocation.getThis() != null?AopUtils.getTargetClass(invocation.getThis()):null;
Method var10001 = invocation.getMethod();
invocation.getClass();
//******重点,通过事务进行工作**** 进入该方法
return this.invokeWithinTransaction(var10001, targetClass, invocation::proceed);
} /**
* 事务拦截器的作用
*/
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
//省略部分非重要代码
//获取事务的属性
TransactionAttribute txAttr = tas != null?tas.getTransactionAttribute(method, targetClass):null;
//获取事务的管理器 ,附源码
PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
//得到要执行的事务方法
String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);
//开启事务
TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(tm, txAttr, joinpointIdentification); try { //invocation 事务方法 下面是执行事务方法
retVal = invocation.proceedWithInvocation();
} catch (Throwable var17) {
//进入源码,发现是通过事务管理器进行回滚
this.completeTransactionAfterThrowing(txInfo, var17);
throw var17;
} finally {
this.cleanupTransactionInfo(txInfo);
} //......
//如果正常执行,则提交事务
this.commitTransactionAfterReturning(txInfo);
return retVal;
} //获取事务管理器的源码,首先会根据Transaction中定义的qualifier值获取管理器
@Nullable
protected PlatformTransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
if(txAttr != null && this.beanFactory != null) {
String qualifier = txAttr.getQualifier();
if(StringUtils.hasText(qualifier)) {
return this.determineQualifiedTransactionManager(this.beanFactory, qualifier); //如果qualifier 是空的则根据 transactionManagerBeanName
} else if(StringUtils.hasText(this.transactionManagerBeanName)) {
return this.determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
} else { //如果都没指定,则根据自动装配的值获取
PlatformTransactionManager defaultTransactionManager = this.asPlatformTransactionManager(this.getTransactionManager());
if(defaultTransactionManager == null) {
defaultTransactionManager = this.asPlatformTransactionManager(this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY));
//这是我们一般会最终调用的地方,会按照类型获取事务管理器 PlatformTransactionManager
if(defaultTransactionManager == null) {
defaultTransactionManager = (PlatformTransactionManager)this.beanFactory.getBean(PlatformTransactionManager.class);
this.transactionManagerCache.putIfAbsent(DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
}
}
return defaultTransactionManager;
}
}
}
}
----关注公众号,获取更多内容----
Spring 事务——源码分析的更多相关文章
- [心得体会]spring事务源码分析
spring事务源码分析 1. 事务的初始化注册(从 @EnableTransactionManagement 开始) @Import(TransactionManagementConfigurati ...
- spring事务源码分析结合mybatis源码(一)
最近想提升,苦逼程序猿,想了想还是拿最熟悉,之前也一直想看但没看的spring源码来看吧,正好最近在弄事务这部分的东西,就看了下,同时写下随笔记录下,以备后查. spring tx源码分析 这里只分析 ...
- Spring事务源码分析专题(一)JdbcTemplate使用及源码分析
Spring中的数据访问,JdbcTemplate使用及源码分析 前言 本系列文章为事务专栏分析文章,整个事务分析专题将按下面这张图完成 对源码分析前,我希望先介绍一下Spring中数据访问的相关内容 ...
- spring事务源码分析结合mybatis源码(三)
下面将结合mybatis源码来分析下,这种持久化框架是如何对connection使用,来达到spring事务的控制. 想要在把mybatis跟spring整合都需要这样一个jar包:mybatis-s ...
- Spring事务源码分析总结
Spring事务是我们日常工作中经常使用的一项技术,Spring提供了编程.注解.aop切面三种方式供我们使用Spring事务,其中编程式事务因为对代码入侵较大所以不被推荐使用,注解和aop切面的方式 ...
- Spring事务源码分析
首先看例子,这例子摘抄自开涛的跟我学spring3. @Test public void testPlatformTransactionManager() { DefaultTransactionDe ...
- spring事务源码分析结合mybatis源码(二)
让我们继续上篇,分析下如果有第二个调用进入的过程. 代码部分主要是下面这个: if (isExistingTransaction(transaction)) { return handleExisti ...
- spring事务源码研读1
转载摘录自:Spring事务源码分析(一)Spring事务入门 有时为了保证一些操作要么都成功,要么都失败,这就需要事务来保证. 传统的jdbc事务如下: @Test public void test ...
- 框架源码系列十一:事务管理(Spring事务管理的特点、事务概念学习、Spring事务使用学习、Spring事务管理API学习、Spring事务源码学习)
一.Spring事务管理的特点 Spring框架为事务管理提供一套统一的抽象,带来的好处有:1. 跨不同事务API的统一的编程模型,无论你使用的是jdbc.jta.jpa.hibernate.2. 支 ...
- Spring AMQP 源码分析 02 - CachingConnectionFactory
### 准备 ## 目标 了解 CachingConnectionFactory 在默认缓存模式下的工作原理 ## 前置知识 <Spring AMQP 源码分析 01 - Impatie ...
随机推荐
- 视觉里程计1-SLAMCP7
--20.11.27 在CP2里面讲到,视觉SLAM主要分为视觉前端以及优化后端,后端也被称为视觉里程计(VO).根据相邻图像的信息,估计粗略的相机运动,给后端提供较好的初始值.VO的实现方法按是否需 ...
- 【LeetCode - 1055】形成字符串的最短路径
1.题目描述 代码: #include <iostream> #include <string> using namespace std; const int MAX_LETT ...
- Debug --> python list.sort()食用方法
list.sort(key=lambda x:x[1] , reverse=True) 参数 key 指明按照什么进行排序.lambda是匿名函数,参数的第一个x表示列表的第一个元素,如表示列表中的元 ...
- SQL Server datetime类型为null的有趣实验
@data1 --变量 测试用 @data2 --当前时间 当@data1为null 则格式转换错误 直接控制台什么也不显示 也不报错 当定义'' 显示默认时间
- 重写mybatis-plus的saveUpdate方法
重写mybatis-plus的saveUpdate方法 1.问题出现 同步外部数据的时候,如果需要同步逻辑删除的数据,mybatis-plus的saveOrUpdate||saveOrUpdateBa ...
- 高并发解决方案之 redis 分布式锁
背景:秒杀服务中要写一个定时任务:活动到期时给order微服务发送关闭订单的通知.这需要改变数据库表中的数据,而集群中服务是多节点的方式进行部署,会出现并发执行的情况,所以采用的redis的分布式锁的 ...
- Python爬虫之Scrapy框架爬虫实战
Python爬虫中Scrapy框架应用非常广泛,经常被人用于属于挖掘.检测以及自动化测试类项目,为啥说Scrapy框架作为半成品我们又该如何利用好呢 ?下面的实战案例值得大家看看. 目录: 1.Scr ...
- spring cloud alibaiba的POM引入
POM添加spring cloud alibaba相关jar包 1 <dependency> 2 <groupId>org.springframework.boot</g ...
- FCC 高级算法题 库存更新
Inventory Update 依照一个存着新进货物的二维数组,更新存着现有库存(在 arr1 中)的二维数组. 如果货物已存在则更新数量 . 如果没有对应货物则把其加入到数组中,更新最新的数量. ...
- Django: sqlite的版本问题小记 “SQLite 3.8.3 or later”
问题概述 在Django中,默认的数据库时SQLite3. 可能会出现sqlite版本问题的报错,具体如下 起初我直接在django的project下面开了个cmd窗口,python python m ...