dubbo源码解析(一)

大家好,我是烤鸭:

     今天和大家分享dubbo的源码解析。


1.SPI

http://dubbo.apache.org/zh-cn/docs/source_code_guide/dubbo-spi.html

介绍:
SPI 全称为 Service Provider Interface,是一种服务发现机制。
SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。
Dubbo重写了Java原生的SPI。Dubbo SPI 是通过键值对的方式进行配置,按需加载指定的实现类。
源码:
com.alibaba.dubbo.common.extension.ExtensionLoader 
getExtension:
获取拓展类对象。

createExtension:
1. 通过 getExtensionClasses 获取所有的拓展类
2. 通过反射创建拓展对象
3. 向拓展对象中注入依赖 (injectExtension)
4. 将拓展对象包裹在相应的 Wrapper 对象中

将产生的wrapper对象放到 objectFactory 。
objectFactory 变量的类型为 AdaptiveExtensionFactory,AdaptiveExtensionFactory 内部维护了一个 ExtensionFactory 列表,用于存储其他类型的 ExtensionFactory。Dubbo 目前提供了两种 ExtensionFactory,分别是 SpiExtensionFactory 和 SpringExtensionFactory。前者用于创建自适应的拓展,后者是用于从 Spring 的 IOC 容器中获取所需的拓展。 
Dubbo IOC 目前仅支持 setter 方式注入。

2.动态加载

http://dubbo.apache.org/zh-cn/docs/source_code_guide/adaptive-extension.html
介绍:
拓展方法被调用时,根据运行时参数进行加载。 Dubbo 会为拓展接口生成具有代理功能的代码。然后通过 javassist 或 jdk 编译这段代码,得到 Class 类。最后再通过反射创建代理类,整个过程比较复杂。
源码:
@Adaptive 
当 Adaptive 注解在类上时,Dubbo 不会为该类生成代理类。注解在方法(接口方法)上时,Dubbo 则会为该方法生成代理逻辑。

com.alibaba.dubbo.common.extension.ExtensionLoader 
getAdaptiveExtension:
创建自适应拓展。
createAdaptiveExtension
1. 调用 getAdaptiveExtensionClass 方法获取自适应拓展 Class 对象
2. 通过反射进行实例化
3. 调用 injectExtension 方法向拓展实例中注入依赖

getAdaptiveExtensionClass
1. 调用 getExtensionClasses 获取所有的拓展类
2. 检查缓存,若缓存不为空,则返回缓存
3. 若缓存为空,则调用 createAdaptiveExtensionClass 创建自适应拓展类动态生成代码(类):
代码生成的顺序与 Java 文件内容顺序一致,首先会生成 package 语句,然后生成 import 语句,紧接着生成类名等代码。

// 生成 package 代码:package + type 所在包
codeBuilder.append("package ").append(type.getPackage().getName()).append(";");
// 生成 import 代码:import + ExtensionLoader 全限定名
codeBuilder.append("\nimport ").append(ExtensionLoader.class.getName()).append(";");
// 生成类代码:public class + type简单名称 + $Adaptive + implements + type全限定名 + {
codeBuilder.append("\npublic class ").append(type.getSimpleName()).append("$Adaptive").append(" implements ").append(type.getCanonicalName()).append(" {");// ${生成方法}codeBuilder.append("\n}");

动态生成代码(方法):
Dubbo 不会为没有标注 Adaptive 注解的方法生成代理逻辑,对于该种类型的方法,仅会生成一句抛出异常的代码。

for (Method method : methods) {// 省略无关逻辑Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class);StringBuilder code = new StringBuilder(512);// 如果方法上无 Adaptive 注解,则生成 throw new UnsupportedOperationException(...) 代码if (adaptiveAnnotation == null) {// 生成的代码格式如下:// throw new UnsupportedOperationException(//     "method " + 方法签名 + of interface + 全限定接口名 + is not adaptive method!”)code.append("throw new UnsupportedOperationException(\"method ").append(method.toString()).append(" of interface ").append(type.getName()).append(" is not adaptive method!\");");} else {// 省略无关逻辑}// 省略无关逻辑
}

 获取 URL 数据:
 要为 Protocol 接口的 refer export 方法生成代理逻辑。
 通过遍历 refer 的参数列表即可获取 URL 数据,export 参数列表中没有 URL 参数,因此需要从 Invoker 参数中获取 URL 数据。获取方式是调用 Invoker 中可返回 URL 的 getter 方法,如果 Invoker 中无相关 getter 方法,此时则会抛出异常。
 生成后如下:

 refer:
if (arg1 == null) throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg1;export:
if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
if (arg0.getUrl() == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
com.alibaba.dubbo.common.URL url = arg0.getUrl();

获取 Adaptive 注解值:
Adaptive 注解值 value 类型为 String[],可填写多个值,默认情况下为空数组。若 value 为非空数组,直接获取数组内容即可。若 value 为空数组,则需进行额外处理。比如 LoadBalance 经过处理后,得到 load.balance

检测 Invocation 参数:
检测方法列表中是否存在 Invocation 类型的参数,若存在,则为其生成判空代码和其他一些代码。

生成拓展名获取逻辑:
本段逻辑用于根据 SPI 和 Adaptive 注解值生成“获取拓展名逻辑”,同时生成逻辑也受 Invocation 类型参数影响,综合因素导致本段逻辑相对复杂。本段逻辑可以会生成但不限于下面的代码:

String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
//或String extName = url.getMethodParameter(methodName, "loadbalance", "random");
//亦或是String extName = url.getParameter("client", url.getParameter("transporter", "netty"));

生成拓展加载与目标方法调用逻辑:
本段代码逻辑用于根据拓展名加载拓展实例,并调用拓展实例的目标方法。
以 Protocol 接口举例说明,上面代码生成的内容如下:

com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
return extension.refer(arg0, arg1);

生成完整的方法:
以 Protocol 的 refer 方法为例,上面代码生成的内容如下:

public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) {// 方法体
}

 

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

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

相关文章

8号团队-团队任务三:每日立会(2018-11-27)

团队信息: 1.团队序号 8 2.开发软件 飞机大战 3.今日整理人:徐浩茗 职位:项目经理 学号:2016035107247 4.本次团队会议共有8人参加 无缺席 团队汇报: (截图)如下 . 4.燃尽图 5.本次会议中遇…

[css] 说说你对低版本IE的盒子模型的理解

[css] 说说你对低版本IE的盒子模型的理解 一个CSS盒子由四部分组成,由内到外依次是:content、padding、border、margin。所谓盒子模型定义的是盒子宽高的计算方法,IE盒子模型的宽高为content、padding、border之和。而W3C盒子的宽高仅为cont…

Alibaba 开源工具 Arthas 使用

大家好,我是烤鸭: 很长时间没更新了,最近太忙了,只能抽空水点文章了,今天给大家介绍的是阿里的开源工具 Arthas 的使用。 1. 开源地址 Arthas 是Alibaba开源的Java诊断工具 https://github.com/alibaba/arthas 中文说…

[css] 你是如何规划响应式布局的?

[css] 你是如何规划响应式布局的? 从项目角度来讲, PC 和 Mobile 是一个项目还是两个项目;从方法流派来讲, 有栅栏布局,固定 viewport,使用 rem/pt/vw 单位,使用定位百分比,修改为 …

Oracle 用户,角色,权限等

权限管理是 Oracle 系统的精华,不同用户登录到同一数据库中,可能看到不同数量的表,拥有不同的权限。Oracle 的权限分为系统权限和数据对象权限,共一百多种,如果单独对用户授权,很囧,有一些用户需…

Java 面试题(4)—— 多线程

Java实现多线程有哪几种方式。 implements Runnable, implements Callable,extends Thread Callable和Future、FutureTask的了解。 Callable和 Future 是juc包下的接口。 Callable 可以异步执行任务,一般和 ExecutorService 的submit方法一起使用。 Future 可以监听…

[css] 如何让大小不同的图片等比缩放不变形显示在固定大小的div里?写个例子

[css] 如何让大小不同的图片等比缩放不变形显示在固定大小的div里?写个例子 图片等比缩放 img{ object-fit: cover/contain;}div宽高比例固定,跟随屏幕变化而变化,利用padding垂直方向的属性来实现个人简介 我是歌谣,欢迎和大家一…

[css] 行内css和important哪个优先级高?

[css] 行内css和important哪个优先级高? !important 将覆盖行内css css优先级:行内css>id选择器(#)>伪类(:)>属性选择器([])>类选择器(.) > 类型选择器(div p a等) > 通用选择器(*)个人简介 我是歌谣,欢迎和大家一起交流…

Password

题目 题解 由打表得对于任意\(i \geq 1\)&#xff0c;都有第\(i1\)行和第\(i3\)行相等、 于是我们可以分块维护一下。 然后做完了。 代码 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm>us…

The temporary upload location [/tmp/tomcat.xxx/work/Tomcat/localhost/etc] is not valid

大家好&#xff0c;我是烤鸭: 下面又来踩坑实录了。主要是两个问题&#xff0c;第一是图片上传异常&#xff0c;第二是下载文件异常。其实都是在服务器上写入失败。有的人说是权限问题&#xff0c;但是这个一直没人动过。 由于过年放假&#xff0c;导致测试环境很长时间…

[css] 说说你对前端二倍图的理解?移动端使用二倍图比一倍图有什么好处?

[css] 说说你对前端二倍图的理解&#xff1f;移动端使用二倍图比一倍图有什么好处&#xff1f; 二倍图是指单位面积下设备像素与css像素个数之比为 4 的位图。移动端使用二倍图可以在Retina屏幕下保真展示。个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃…

人生苦短,我用python

0.10 |— 模块1&#xff1a;开发基础(23)0.11 |— 模块2&#xff1a;文件、函数、模块(29)0.12 |— 模块3&#xff1a;OO、网络编程(19)0.13 |— 模块4&#xff1a;并发编程(13)0.14 |— 模块5&#xff1a;Mysql数据库(16)0.15 |— 模块6&#xff1a;web前端开发(34)0.16 |— 模…

spring 多线程 事务 源码解析(一)

大家好&#xff0c;我是烤鸭&#xff1a; 今天分享的是spring 多线程事务源码分析。 环境&#xff1a; spring-jdbc 5.0.4.REALEASE 今天分享一下spring事务的方法&#xff0c;这一篇还没涉及到多线程。 简单说一下doBegin的方法&#xff1a; 强转获取当前的事务对象&#…

[css] 你对视网膜(Retina)分辨率有了解吗?有没有在实际中使用过?

[css] 你对视网膜(Retina)分辨率有了解吗&#xff1f;有没有在实际中使用过&#xff1f; Retina分辨率指的是屏幕的物理分辨率达到了使得人眼难以看到单个物理像素&#xff1b;具体应用应该就是dpr > 1的屏幕适配&#xff0c;需要根据不同dpr给出合适尺寸的图片&#xff1b;…

Java学习之斐波那契数列实现

描述 一个斐波那契序列&#xff0c;F(0) 0, F(1) 1, F(n) F(n-1) F(n-2) (n>2)&#xff0c;根据n的值&#xff0c;计算斐波那契数F(n)&#xff0c;其中0≤n≤1000。 输入 输入数据的第一行为测试用例的个数t&#xff0c;接下来为t行&#xff0c;每行为一个整数n&#x…

[css] 移动端微信页面有哪些兼容性问题及解决方案是什么?

[css] 移动端微信页面有哪些兼容性问题及解决方案是什么&#xff1f; 1.rem方案通过reset js进行适配 2.vw 方案 搭配px to viewport进行适配个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 …

spring 多线程 事务的实际应用场景

大家好&#xff0c;我是烤鸭&#xff1a; 今天分享的是spring 多线程 事务的实际应用场景&#xff1a; 上一篇讲了大概的原理,主要是针对事务的开始和执行过程(数据库链接&#xff0c;隔离级别&#xff0c;threadlocal线程绑定)。https://blog.csdn.net/Angry_Mills/article/…

Redis的过期策略和内存淘汰机制

过期策略 我们set key的时候&#xff0c;都可以给一个expire time&#xff0c;就是过期时间&#xff0c;指定这个key比如说只能存活1个小时&#xff0c;我们自己可以指定缓存到期就失效。 如果假设你设置一个一批key只能存活1个小时&#xff0c;那么接下来1小时后&#xff0c;r…

[css] 如何更改placeholder的字体颜色和大小?

[css] 如何更改placeholder的字体颜色和大小&#xff1f; <style>/* Chrome浏览器 */input::-webkit-input-placeholder {color: red;}/* 火狐浏览器 */input::-moz-placeholder {color: red;}/* IE */input:-ms-input-placeholder {color: red;}</style> <body…

[maven] springboot将jar包打包到指定目录

大家好&#xff0c;我是烤鸭&#xff1a; 今天分享一下springboot将jar包打包到指定目录下。 由于之前上线都是一个打包到一个jar&#xff0c;由于服务多了&#xff0c;1个包100多M&#xff0c;哪怕是小版本上线都需要重新上传jar包。 1.目的 将不常用的比如spring,druid等不常…