IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Dubbo的适配器原理、动态编译原理 -> 正文阅读

[Java知识库]Dubbo的适配器原理、动态编译原理

适配器原理、动态编译原理

适配器原理

Dubbo 为 每个功能点 提供了 一个SPI扩展接口,Dubbo框架 在使用 扩展点功能的时候 是对 接口进行依赖的,而一个扩展接口 对应了 一系列的扩展实现类

那么如何选择 使用哪一个 扩展接口的实现类呢
其实这是 使用 适配器模式 来做的

首先看看什么是适配器模式,比如Dubbo提供的扩展接口Protocol,其定义如下

@SPI("dubbo")
public interface Protocol {
	// 自适应
	@Adaptive
    <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;

	@Adaptive
    <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
}

Dubbo会使用 动态编译技术 为接口 Protocol 生成一个 适配器类Protocol$Adaptive的对象实例
在Dubbo框架中 需要使用 Protocol的实例时,实际上就是 使用 Protocol$Adaptive 的 对象实例 来获取 具体的SPI实现类,其代码如下
在这里插入图片描述

在这里插入图片描述
在Dubbo框架中,protocol的定义为:
private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
当调用protocol.export (wrapperInvoker)时,实际 是调用 Protocol$Adaptive的对象实例 的 export()方法
然后 后者 根据 wrapperInvoker中 URL里面 的 协议类型参数 执行
代码2使用Dubbo增强SPI方法getExtension() 获取 对应的 SPI实现类
然后调用代码3 来执行 具体SPI实现类的export()方法

需要注意的是,在Dubbo中URL是一个核心概念,Dubbo框架把所需的参数都拼接到了URL对象里

这里假设代码2传递的协议类型为Dubbo,则说明 使用 增强SPI 返回 扩展接口Protocol 的 Dubbo实现,即返回了DubboProtocol的实例
那么代码3则返回调用DubboProtocol的export()方法的返回结果
也就是说 当框架 调用protocol.export(wrapperInvoker)时,实际上是调用了DubboProtocol的export()方法

总结一下就是,适配器类Protocol$Adaptive会根据传递的协议参数的不同,加载不同的Protocol的SPI实现

其实在Dubbo框架中,框架 会给每个SPI扩展接口 动态生成一个 对应的 适配器类,并根据 参数 来使用 增强SPI 以选择 不同的SPI实现
比如扩展接口ProxyFactory的适配器类为ProxyFactory$Adaptive,其根据参数proxy来选择使用JdkProxyFactory还是使用JavassistProxyFactory做代理工厂
扩展接口Registry的适配器类Registry$Adaptive则根据参数register来决定使用ZookeeperRegistry、RedisRegistry、MulticastRegistry、DubboRegistry中的哪一个作为服务注册中心等

动态编译原理

在Dubbo框架中 框架 会给 每个SPI扩展接口 动态生成 一个 对应的 适配器类
那么如何生成呢?这里就使用了动态编译技术
在Dubbo中提供了一个Compiler的SPI

package org.apache.dubbo.common.compiler;

import org.apache.dubbo.common.extension.SPI;

/**
 * Compiler. (SPI, Singleton, ThreadSafe)
 */
@SPI("javassist")
public interface Compiler {

    /**
     * Compile java source code.
     *
     * @param code        Java source code
     * @param classLoader classloader
     * @return Compiled class
     */
    Class<?> compile(String code, ClassLoader classLoader);

}

Dubbo提供Compiler的实现有JavassistCompiler(默认实现)和JdkCompiler两种

从 Dubbo框架 如何使用 动态编译 生成扩展接口 对应的 适配器类 入手
首先看ExtensionLoader的createAdaptiveExtensionClass()方法,就是该方法 将源文件 动态编译为 Class对象的,有了Class对象后,就可以使用newInstance()方法创建对象实例了
在这里插入图片描述
代码1 是根据 SPI扩展接口 生成 其对应的 适配器类的源码,其返回的是一个字符串
比如对于Protocol扩展接口来说,返回的字符串内容为
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码2 使用 增强SPI 选择 扩展接口Compiler的实现,这里默认为JavassistCompiler
然后代码3 调用 JavassistCompiler的compile()方法 并根据 源代码 生成 Protocol/$Adaptive 的 Class对象

总结一下就是,Dubbo框架 会为 每个扩展接口 生成 其对应的 适配器类的源码
然后 选择 具体的 动态编译类 的 扩展实现 对源码 进行 编译 以 生成 适配器类的Class对象
然后 就可以 调用Class对象 的 newInstance()方法 生成 扩展接口 对应的 适配器类 的 实例

具体相关源码可见Dubbo-SPI(四)-@Adaptive注解

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-09-04 17:22:29  更:2021-09-04 17:24:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:14:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码