Spring-事务源码解析2

上一篇文章我们介绍了事务开启注解@EnableTransactionManagement源码解析《Spring-事务源码解析1》 里面提到了2个关键组件,这里我们分析下Spring如何利用这2个组件来给Bean创建代理对象。

文章待整理

先说下执行流程,当请求进来的时候,会执行JdkDynamicAopProxy的invoke方法,这时会拿到方法的拦截器链,下面是获取目标方法的拦截器链

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

然后执行拦截器链中的最开始的拦截器,后面一次遍历,但是此时的拦截器就只有一个就是TransactionInterceptor事务方法拦截器

进到TransactionInterceptor就会执行TransactionInterceptor的invoke方法,下面看下invoke的流程

1、先拿到事务管理器的事务类型:PROPAGATION_REQUIRED,ISOLATION_DEFAULT;
2、在拿到事务的管理器也就是DataSourceTransactionManager

@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {//目标类      Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);//执行切面方法和目标方法return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {@Overridepublic Object proceedWithInvocation() throws Throwable {return invocation.proceed();}});
}protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) throws Throwable {//1、事务隔离级别final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);//2、事务管理器DataSourceTransactionManagerfinal PlatformTransactionManager tm = determineTransactionManager(txAttr);//生成事务txInfo,里面包含本次事务状态,隔离级别,事务处理器,当本次事务执行完后需要关闭本次事务TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);try {//执行进入下一个链,此时只有一个也就是目标方法retVal = invocation.proceedWithInvocation();}catch (Throwable ex) {//更改txInfo里面的状态completeTransactionAfterThrowing(txInfo, ex);throw ex;}finally {cleanupTransactionInfo(txInfo);}commitTransactionAfterReturning(txInfo);//根据状态是否commitreturn retVal;
}

五、疑问

1、带有@Transaction注解的Bean实例化的时候,怎么如果判断该Bean带有@Transaction方法

1、InfrastructureAdvisorAutoProxyCreator#postProcessAfterInitialization
—>2、BeanFactoryTransactionAttributeSourceAdvisor
—>3、AnnotationTransactionAttributeSource
—>4、SpringTransactionAnnotationParser判断@Transaction

最终通过SpringTransactionAnnotationParser来判断Bean的方法是否带有@Transaction注解

拓展:
InfrastructureAdvisorAutoProxyCreator里面有个advisedBeans属性,在Bean的创建过程会判断Bean里面 是否是带有事务注解@Transaction的方法,如果有就会被加到advisedBeans里面去。

private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<Object, Boolean>(256);

注意:
1、BeanFactoryTransactionAttributeSourceAdvisor事务增强器在advisedBeans是false的形式存在
2、transactionInterceptor也是false

2、带有@Transaction注解的代理Bean在哪个流程被创建

在执行BeanPostProcess处理器链的时候,由InfrastructureAdvisorAutoProxyCreator#postProcessAfterInitialization方法执行创建,该方法会调用wrapIfNecessary方法完成代理创建

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {.......//这里是拿到BeanFactoryTransactionAttributeSourceAdvisor也就是“事务增强器”Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);//key就是带有@Transaction的BeanNameObject proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));return proxy;//返回代理对象}return bean;
}

3、如何创建@Transaction注解的Bean
默认是使用JDK动态代理

1、先创建ProxyFactory对象,设置属性
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTargetSource(目标对象LLServcieImpl);
proxyFactory.setInterfaces(目标接口LLServcie);
proxyFactory.addAdvisor(事务增强器BeanFactoryTransactionAttributeSourceAdvisor);
proxyFactory.getProxy(getProxyClassLoader())//调用下面的代码
//2、生成动态代理对象
proxiedInterfaces=AopProxyUtils.completeProxiedInterfaces(事务增强器, true);
//设置代理对象要实现接口和InvocationHandler对象
Proxy.newProxyInstance(classLoader, proxiedInterfaces, JdkDynamicAopProxy);

其中proxiedInterfaces包含接口

0 = {Class@3511} “interface cn.tedu.sample2.util.LLServcie”
1 = {Class@3676} “interface org.springframework.aop.SpringProxy”
2 = {Class@5780} “interface org.springframework.aop.framework.Advised”
3 = {Class@3897} “interface org.springframework.core.DecoratingProxy”

4、InfrastructureAdvisorAutoProxyCreator类的作用

1、postProcessBeforeInstantiation方法主要是针对所有要创建的Bean,判断存到advisedBeans里面是false还是true
2、postProcessAfterInitialization方法,处理带有@Transcation的Bean,创建代理Bean

六、总结

1、先通过@EnableTransactionManagement引入TransactionManagementConfigurationSelector
2、通过TransactionManagementConfigurationSelector,导入AutoProxyRegistrar,ProxyTransactionManagementConfiguration
3、AutoProxyRegistrar会向容器中注册InfrastructureAdvisorAutoProxyCreator
4、ProxyTransactionManagementConfiguration会向容器定义三个Bean:事务增强器、@Transaction注解解析器、事务方法拦截器
5、执行Bean的后置处理器时,通过InfrastructureAdvisorAutoProxyCreator的postProcessAfterInitialization方法创建代理对象
6、创建代理对象时,通过事务增强器BeanFactoryTransactionAttributeSourceAdvisor来得到代理类要实现的接口SpringProxy、Advised、DecoratingProxy,最终生成代理对象

7、当请求进来时,先进入JdkDynamicAopProxy的invoke方法
8、invoke里面会调用TransactionInterceptor的invoke方法,里面会调用invokeWithinTransaction方法
9、invokeWithinTransaction里面会在调用目标方法前开启事务,catch失败设置状态,然后finally根据状态来确认是否commit

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/156787.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql sql语句遍历树结构

mysqlsql语句遍历树结构 MySQL SQL语句遍历树结构实现步骤 理解树结构和遍历算法 在开始之前&#xff0c;我们首先需要了解什么是树结构以及如何遍历树结构。树结构是一种常用的数据结构&#xff0c;由各个节点和节点之间的关系构成。树结构的一个重要应用是表示具有层级关系…

UE4和C++ 开发-C++与UMG的交互2(C++获取UMG的属性)

1、...C获取UMG的属性 1.1、第一种方法&#xff1a;通过名称获取控件。 void UMyUserWidget::NativeConstruct() {Super::NativeConstruct();//通过名字&#xff0c;获取蓝图控件中的按钮引用。CtnClic Cast<UButton>(GetWidgetFromName(TEXT("Button_44"))…

企业精密空调运营,这才是最好的方法!

机房是现代企业和组织的核心&#xff0c;其中承载着重要的服务器和网络设备&#xff0c;为业务的持续运行提供支持。 机房内的温度、湿度和空气质量对设备的性能和可靠性至关重要。精密空调监控系统通过实时监测和智能控制&#xff0c;确保机房的环境条件始终在最佳状态&#x…

同城跑腿微信小程序源码系统完整搭建教程

今天给大家分享一个同城跑腿微信小程序源码系统的完整搭建教程&#xff0c;源代码全部开源&#xff0c;可二次开发&#xff0c;搭建起来也比较简单。 系统具体功能一览&#xff1a; 地图定位&#xff1a;用户可以通过地图定位找到附近的跑腿服务商&#xff0c;方便快捷。在线下…

生活中的视音频技术

生活中的视音频技术 平时我们打开电脑中自己存电影的目录的话&#xff0c;一般都会如下图所示&#xff0c;一大堆五花八门的电影。&#xff08;其实专业的影视爱好者一概会把影视文件分门别类的&#xff0c;但我比较懒&#xff0c;一股脑把电影放在了一起&#xff09; 因为下载…

【C#】标准WebService Soap1.1 兼容 ContentType: application/xml

一、问题描述 1.1 ESB平台要求 ContentType&#xff1a;application/xml Soap协议版本&#xff1a;1.1 1.2 提供的 WebService 接口 语言&#xff1a;C# 目标框架&#xff1a;.NetFramework 4.6.1 1.3 Postman 测试结果 HTTP Error 415.0 - Unsupported Media Type 服务器…

用什么工具来画UML?

2023年10月9日&#xff0c;周一晚上 目录 我的决定 关于rational rose UML工具有哪些 相关资料 我的决定 我决定用plantUML、draw.io或starUML就可以了 其实没必要在意工具&#xff0c; 重要的是能把图画出来、把图画好画规范&#xff0c; 重要的是知道怎么去画图、把意…

vue3 + element Plus实现表格根据关键字合并行,并实现行的增删改操作

根据关键字合并表格 1.实现初始化表格2.实现添加班级与学生的功能3.添加的弹窗4.删除班级5.删除学生 首先看最终实现的效果 1.实现初始化表格 这里主要用到的是表格的span-method这个方法 <template><div class"main-page"><div class"flex-en…

多线程锁-死锁案例和排查命令

3.5 死锁及排查 3.5.1 概念 死锁是指两个或两个以上的线程在执行过程中&#xff0c;因抢夺资源而造成的一种互相等待的现象&#xff0c;若无外 力干涉&#xff0c;则它们无法再继续推进下去。 产生原因&#xff1a; 系统资源不足进程运行推进顺序不合适系统资源分配不当 3…

MongoDB 索引和常用命令

一、基本常用命令 1.1 案例需求 存放文章评论的数据存放到 MongoDB 中&#xff0c;数据结构参考如下&#xff0c;其中数据库为 articledb&#xff0c; 专栏文章评论 comment 字段名称 字段含义 字段类型 备注 _id ID ObjectId或String Mongo的主键的字段 articlei…

Android Studio新建项目教程

Android Studio新建项目教程 一、创建新项目 二、选择空白页项目类型 配置然后finish 等待项目完成初试化 等待初始化结束&#xff0c;创建完成 三、运行创建的APP

京东历史价格数据接口,京东商品历史价格接口,京东API接口

京东商品历史价格数据接口采集方法如下&#xff1a; 注册京东开发者账号&#xff0c;并创建应用&#xff0c;获取到应用ID&#xff08;appID&#xff09;、应用密钥&#xff08;appSecret&#xff09;以及访问令牌&#xff08;accessToken&#xff09;。获取接口请求地址。根据…

华为数通方向HCIP-DataCom H12-831题库(单选题:241-260)

第241题 某园区部署了IPV6进行业务测试,该网络中有4台路由器(R1R2、R3和R),运行OSPFV3实现Pv6网络的互联互通。有一台新的路由器R5需要接入网络进行测试,某工程师通过在R4的OSPFV3进程中引入直连路由,实现园区网内的设备能够访问R5的GEO/0/1口地址。关千该场景的描述,错误…

云计算到底牛x在哪里?

你们好&#xff0c;我的网工朋友。 云计算已经霸屏行业有段时间了&#xff0c;但很多粉丝朋友还是不太明白什么是云计算&#xff0c;为什么要学云计算。 从宏观来说&#xff0c;其实云计算的优点很多。 就和传统模式相比&#xff0c;云计算在六个维度都有显著的提升点。 比…

Vue-2.7自定义指令

自定义指令 自己定义的指令&#xff0c;可以封装一些dom操作&#xff0c;扩展额外功能 例如需求&#xff1a;当页面加载时&#xff0c;让元素将获得焦点&#xff08;autofucus在safari浏览器有兼容性&#xff09; 操作dom&#xff1a;dom元素.focus() 太麻烦&#xff01;…

Zend Framework 3.1.3 gadget chain

前言 在推特上的PT SWARM账号发布了一条消息。 一个名为Zend Framework的php框架出现了新的gadget chain&#xff0c;可导致RCE。笔者尝试复现&#xff0c;但失败了。所幸&#xff0c;我基于此链&#xff0c;发现在这个框架的最新版本中的另一条链。 复现过程 这里使用vscod…

ArcGIS/GeoScene脚本:基于粒子群优化的支持向量机回归模型

参数输入 1.样本数据必须包含需要回归的字段 2.回归字段是数值类型 3.影响因子是栅格数据&#xff0c;可添加多个 4.随机种子可以确保每次运行的训练集和测试集一致 5.训练集占比为0-1之间的小数 6.迭代次数&#xff1a;迭代次数越高精度越高&#xff0c;但是运行时间越长…

机器学习 - 似然函数:概念、应用与代码实例

目录 一、概要二、什么是似然函数数学定义似然与概率的区别重要性举例 三、似然函数与概率密度函数似然函数&#xff08;Likelihood Function&#xff09;定义例子 概率密度函数&#xff08;Probability Density Function, PDF&#xff09;定义 区别与联系 四、最大似然估计&am…

网络流量安全分析-工作组异常

在网络中&#xff0c;工作组异常分析具有重要意义。以下是网络中工作组异常分析的几个关键点&#xff1a; 检测网络攻击&#xff1a;网络中的工作组异常可能是由恶意活动引起的&#xff0c;如网络攻击、病毒感染、黑客入侵等。通过对工作组异常的监控和分析&#xff0c;可以快…

8年经验之谈 —— 如何用 JMeter 编写性能测试脚本?

Apache JMeter 应该是应用最广泛的性能测试工具。怎么用 JMeter 编写性能测试脚本&#xff1f; 1. 编写 HTTP 性能测试脚本 STEP 1. 添加 HTTP 请求 i STEP 2. 了解配置信息 HTTP 请求各项信息说明&#xff08;以 JMeter 5.1 为例&#xff09;。 如下图所示&#xff1a; W…