seata源码分析(03)_创建代理的过程

seata提供了ProxyUtil工具类为事务组件创建代理对象,在spring环境中,seata提供了GlobalTransactionScanner类和SeataAutoDataSourceProxyCreator为组件创建AOP代理,本文重点分析这两个类。

ProxyUtil

io.seata.integration.tx.api.util.ProxyUtil类。

public class ProxyUtil {private static final Map<Object, Object> PROXYED_SET = new HashMap<>();public static <T> T createProxy(T target) {return createProxy(target, target.getClass().getName());}public static <T> T createProxy(T target, String beanName) {try {synchronized (PROXYED_SET) {if (PROXYED_SET.containsKey(target)) {return (T) PROXYED_SET.get(target);}// 使用InterfaceParser获取与target对应的ProxyInvocationHandler// 1. GlobalTransactionalInterceptorHandler// 2. TccActionInterceptorHandler// 内部检查@GlobalTransactional、@GlobalLock、// @TwoPhaseBusinessAction等注解,来判断是否需要创建代理ProxyInvocationHandler proxyInvocationHandler =DefaultInterfaceParser.get().parserInterfaceToProxy(target, beanName);if (proxyInvocationHandler == null) {return target;}// 创建代理对象// 把proxyInvocationHandler注入到拦截逻辑中// DefaultInvocationHandler实现了java InvocationHandler接口// invoke方法会执行proxyInvocationHandler的代理逻辑T proxy = (T) new ByteBuddy().subclass(target.getClass()).method(isDeclaredBy(target.getClass())).intercept(InvocationHandlerAdapter.of(new DefaultInvocationHandler(proxyInvocationHandler, target))).make().load(target.getClass().getClassLoader()).getLoaded().getDeclaredConstructor().newInstance();PROXYED_SET.put(target, proxy);return proxy;}} catch (Throwable t) {throw new RuntimeException("error occurs when create seata proxy", t);}}
}

DefaultInvocationHandler

public class DefaultInvocationHandler implements InvocationHandler {private ProxyInvocationHandler proxyInvocationHandler;private Object delegate;public DefaultInvocationHandler(ProxyInvocationHandler proxyInvocationHandler, Object delegate) {this.proxyInvocationHandler = proxyInvocationHandler;this.delegate = delegate;}// 动态代理逻辑@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {InvocationWrapper invocation = new DefaultInvocationWrapper(proxy, delegate, method, args);Object result;if (proxyInvocationHandler != null) {result = proxyInvocationHandler.invoke(invocation);} else {result = invocation.proceed();}return result;}
}

GlobalTransactionScanner

继承了spring的AbstractAutoProxyCreator类:

  • 初始化TM和RM客户端
  • 为seata的事务组件创建AOP代理

initClient方法创建TM和RM客户端

使用seata提供的TMClient和RMClient工具栏初始化TM、RM客户端:

private void initClient() {// ...if (StringUtils.isNullOrEmpty(applicationId) || StringUtils.isNullOrEmpty(txServiceGroup)) {throw new IllegalArgumentException(String.format("applicationId: %s, txServiceGroup: %s", applicationId, txServiceGroup));}// 创建TmNettyRemotingClientTMClient.init(applicationId, txServiceGroup, accessKey, secretKey);// 创建RmNettyRemotingClientRMClient.init(applicationId, txServiceGroup);// 优雅关闭客户端registerSpringShutdownHook();
}

wrapIfNecessary方法创建AOP代理

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// do checkersif (!doCheckers(bean, beanName)) {return bean;}try {synchronized (PROXYED_SET) {if (PROXYED_SET.contains(beanName)) {return bean;}interceptor = null;// 和ProxyUtil工具类一样ProxyInvocationHandler proxyInvocationHandler =DefaultInterfaceParser.get().parserInterfaceToProxy(bean, beanName);// 如果proxyInvocationHandler为null表示不需要AOP代理if (proxyInvocationHandler == null) {return bean;}// AdapterSpringSeataInterceptor实现了MethodInterceptor接口// 用来封装spring aop的代理拦截逻辑// 这是spring aop的原理,此处不展开分析interceptor = new AdapterSpringSeataInterceptor(proxyInvocationHandler);if (!AopUtils.isAopProxy(bean)) {// 如果bean不是一个代理对象则使用父类方法创建代理对象bean = super.wrapIfNecessary(bean, beanName, cacheKey);} else {// 如果bean已经是一个代理对象// 则需要将事务拦截逻辑添加到代理通知集AdvisedSupport advised = SpringProxyUtils.getAdvisedSupport(bean);Advisor[] advisor = buildAdvisors(beanName, getAdvicesAndAdvisorsForBean(null, null, null));int pos;for (Advisor avr : advisor) {pos = findAddSeataAdvisorPosition(advised, avr);advised.addAdvisor(pos, avr);}}PROXYED_SET.add(beanName);return bean;}} catch (Exception exx) {throw new RuntimeException(exx);}
}

AdapterSpringSeataInterceptor

public class AdapterSpringSeataInterceptor implements MethodInterceptor, SeataInterceptor, Ordered {private ProxyInvocationHandler proxyInvocationHandler;public AdapterSpringSeataInterceptor(ProxyInvocationHandler proxyInvocationHandler) {this.proxyInvocationHandler = proxyInvocationHandler;}@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {AdapterInvocationWrapper adapterInvocationWrapper = new AdapterInvocationWrapper(invocation);Object result = proxyInvocationHandler.invoke(adapterInvocationWrapper);return result;}@Overridepublic int getOrder() {return proxyInvocationHandler.getOrder();}@Overridepublic void setOrder(int order) {proxyInvocationHandler.setOrder(order);}@Overridepublic SeataInterceptorPosition getPosition() {return proxyInvocationHandler.getPosition();}@Overridepublic String toString() {return proxyInvocationHandler.getClass().getName();}
}

SeataAutoConfiguration配置类

用来装配GlobalTransactionScanner组件。

SeataAutoDataSourceProxyCreator

在spring环境中,将原始的DataSource保证为SeataDataSourceProxy对象。

SeataDataSourceAutoConfiguration配置类

用来装配SeataAutoDataSourceProxyCreator组件。

ProxyInvocationHandler

用来封装代理的拦截逻辑。

接口定义

public interface ProxyInvocationHandler extends SeataInterceptor {Set<String> getMethodsToProxy();// 代理拦截逻辑Object invoke(InvocationWrapper invocation) throws Throwable;SeataInterceptorPosition getPosition();
}

实现类

ProxyInvocationHandler|-- AbstractProxyInvocationHandler|-- GlobalTransactionalInterceptorHandler|-- TccActionInterceptorHandler

AbstractProxyInvocationHandler

使用模板方法封装通用的代理检查逻辑:

public abstract class AbstractProxyInvocationHandler implements ProxyInvocationHandler {// 子类实现具体的代理逻辑protected abstract Object doInvoke(InvocationWrapper invocation) throws Throwable;protected int order = Integer.MAX_VALUE;@Overridepublic Object invoke(InvocationWrapper invocation) throws Throwable {if (CollectionUtils.isNotEmpty(getMethodsToProxy()) &&!getMethodsToProxy().contains(invocation.getMethod().getName())) {return invocation.proceed();}return doInvoke(invocation);}// 其他方法 略
}

GlobalTransactionalInterceptorHandler

The type Global transactional interceptor handler.

处理@GlobalTransactional和@GlobalLock注解。

TccActionInterceptorHandler

处理@TwoPhaseBusinessAction注解。

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

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

相关文章

【中年危机】程序猿自救指南

中年危机&#xff0c;一个听起来就充满挑战的词汇&#xff0c;它不仅仅是一个年龄的标记&#xff0c;更是一个个人成长和职业发展的转折点。 构架个人品牌&#xff1a; 学会打造IP个人品牌是职业生涯中的重要资产。在中年时期&#xff0c;你已经积累了丰富的经验和知识&#x…

golang的http客户端封装

简介 net/http 是 Go 语言标准库的一部分&#xff0c;它提供了创建 HTTP 客户端和服务器的能力。这个包通过简化与 HTTP 协议的交互&#xff0c;让开发者能够方便地构建 HTTP 请求和响应&#xff0c;以及处理路由等任务。 本文以 net/http 包作为底层&#xff0c;封装一个包含…

HTCC电路板是什么,有哪些主要应用领域

HTCC英文名称是High-Temperature Co-Fired Ceramic&#xff0c;又称高温共烧多层陶瓷基板。因其具有导热系数高、耐热性好、热膨胀系数小、机械强度高、绝缘性好、耐腐蚀等优势&#xff0c;是保持高速增加的PCB线路板之一。 SPEA作为专业电路板测试设备方案服务商&#xff0c;公…

FY-SA-20237·8-WhyWeSpin

Translated from the Scientific American, July/August 2023 issue. Why We Spin (我们为什么旋转) Primates may play with reality by twirling around 翻译&#xff1a;灵长类动物有能力通过旋转或旋转运动来操纵或扭曲他们对现实的感知。 解释&#xff1a; “Primates”…

Java生成指定长度验证码

生成指定长度验证码的简单思路在Java中通常涉及以下几个步骤&#xff1a; 1、定义字符池&#xff1a; 首先&#xff0c;需要定义一个包含所有可能字符的字符串&#xff0c;这个字符池通常包括数字(0-9)、大写字母(A-Z)、小写字母(a-z)。 例如&#xff1a; String chars "…

【开发心得】三步本地化部署llama3大模型

目录 第一步&#xff1a;启动ollama 第二步&#xff1a;启动dify 第三步&#xff1a;配置模型&#xff08;截图&#xff09; 最近llama3很火&#xff0c;本文追击热点&#xff0c;做一个本地化部署的尝试&#xff0c;结果还成功了&#xff01; 当然也是站在别人的肩膀上&…

【运维项目经历|027】PXE自动化部署与管理平台

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…

Nginx企业级负载均衡:技术详解系列(18)—— 作为上传服务器

你好&#xff0c;我是赵兴晨&#xff0c;97年文科程序员。 在上一期的技术分享中&#xff0c;我们探讨了如何高效搭建Nginx下载服务器&#xff0c;并讨论了长连接优化策略。那么今天&#xff0c;咱们进一步了解Nginx的另一面——作为上传服务器的配置技巧。 作为上传服务器&a…

怎么做好企业短信服务呢?(文字短信XML接口示例)

企业短信服务已经成为各行各业都信赖的行业推广方式之一&#xff0c;并且短信行业也与时俱进的发展着&#xff0c;随之而来的就是市场上短信平台的数量也随之增多。那么怎么在鱼龙混杂的短信行业中选择适合自己的企业短信服务平台呢&#xff1f;企业短信服务平台又适用于哪些应…

Django的PATH路径转换器

本书1-7章样章及配套资源下载链接: https://pan.baidu.com/s/1OGmhHxEMf2ZdozkUnDkAkA?pwdnanc 源码、PPT课件、教学视频等&#xff0c;可以从前言给出的下载信息下载&#xff0c;大家可以评估一下。 在Django框架中&#xff0c;默认内置了一组PATH路径转换器&#xff0c;具…

第一篇【传奇开心果系列】AI工业应用经典算法和Python示例:基于AI的智能制造技术经典算法与Python实践

传奇开心果博文系列 系列博文目录AI工业应用经典算法和Python示例系列 博文目录前言一、AI在智能制造方面的应用场景介绍二、基于AI的智能制造技术经典算法介绍三、支持向量机机器学习算法Python示例代码四、随机森林机器学习算法Python示例代码五、深度学习算法Python示例代码…

linux指令-高阶指令用法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 linux操作系统的环境变量的使用基础需要先了解 提示&#xff1a;以下是本篇文章正文…

【linux】(2)文件内容排序sort

sort 是一个用于排序文件内容的命令行工具&#xff0c;在 Linux 和 Unix 系统中非常常用。 基本用法 sort [OPTION]... [FILE]...常用选项 按数值排序 -n sort -n filename例子&#xff1a;对包含数值的文件进行排序。 按字典顺序排序 -d sort -d filename例子&#xff1…

大宋咨询(深圳酒店神秘顾客调查)酒店客房神秘人体验调查内容

酒店客房神秘检查内容&#xff0c;是酒店管理中至关重要的环节。通过专业的神秘顾客对客房进行细致入微的检查&#xff0c;可以确保客房的清洁度、设施设备的完好性以及服务质量等方面达到高标准&#xff0c;帮助他们更好地了解客户的需求和满意度&#xff0c;从而提高服务质量…

Facebook开户|Facebook公共主页疑难杂症详解

​​要要切克闹&#xff0c;公共主页我来道...哈喽呀家人们中午好&#xff0c;上一次学习还是在上一次..hhh相信很多家人在做Facebook的时候总会遇到各种各样匪夷所思的bug&#xff01;经常被搞心态吧&#xff01;那么咱们今天呢就来总结一下各类的bug以及解决方法&#xff0c;…

InvokeAI学习教程三:换脸

启动InvokeAI&#xff0c;我们先生成一张图&#xff1a; 在正向提示词里输入&#xff1a;Avant-garde couture, tactile textures, vogue aesthetics, vibrant color palette, intricate embroidery details, dramatic silhouettes 生成一张高贵夫人的图像&#xff0c; 或者你从…

标准发布 | 废水处理减污降碳协同评估指南(碳中和标准)

本文件主编单位&#xff1a;北京林业大学、北京交通大学、中国电建集团华东勘测设计研究院有限公司、 眉山市城投中恒能环保科技有限公司、 中华环保联合会水环境治理专业委员会。 本文件参编单位&#xff1a;中国市政工程中南设计研究总院有限公司、湖北君集环境科技股份有 公…

C++ B (1124) : 斐波那契数列第n项Plus

文章目录 一、题目描述二、参考代码 一、题目描述 二、参考代码 #include <iostream> #include <vector>using namespace std;const long long MOD 1e9 7; // 取模的值// 定义矩阵类 class Matrix { public:vector<vector<long long>> data;// 构造…

JavaWeb项目规范开发流程详细分解

在JavaWeb项目开发中&#xff0c;遵循规范化的开发流程和最佳实践可以提高代码的可维护性、可扩展性和团队协作效率。规范化的开发流程主要从下面几个方面进行&#xff1a; 1. 项目结构 分层架构&#xff1a;典型的分层架构包括表示层&#xff08;Controller&#xff09;、业…

字节裁员!开启裁员新模式。。

最近&#xff0c;互联网圈不太平&#xff0c;裁员消息此起彼伏。而一向以“狼性文化”著称的字节跳动&#xff0c;却玩起了“低调裁员”&#xff0c;用一种近乎“温柔”的方式&#xff0c;慢慢挤掉“冗余”的员工。 “细水长流”&#xff1a;裁员新模式&#xff1f; 不同于以往…