AI实践哪家强?来 AICon, 解锁技术前沿,探寻产业新机! 了解详情
写点什么

Dubbo 源码解析之 SPI(一):扩展类的加载过程(上)

  • 2020-02-06
  • 本文字数:1354 字

    阅读完需:约 4 分钟

Dubbo源码解析之SPI(一):扩展类的加载过程(上)

Dubbo 是一款开源的、高性能且轻量级的 Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用、智能容错和负载均衡,以及服务自动注册和发现。


Dubbo 最早是阿里公司内部的 RPC 框架,于 2011 年开源,之后迅速成为国内该类开源项目的佼佼者,2018 年 2 月,通过投票正式成为 Apache 基金会孵化项目。目前宜信公司内部也有不少项目在使用 Dubbo。


本系列文章通过拆解 Dubbo 源码,帮助大家了解 Dubbo,做到知其然,并且知其所以然。

一、JDK SPI

1.1 什么是 SPI?

SPI(Service Provider Interface),即服务提供方接口,是 JDK 内置的一种服务提供机制。在写程序的时候,一般都推荐面向接口编程,这样做的好处是:降低了程序的耦合性,有利于程序的扩展。


SPI 也秉承这种理念,提供了统一的服务接口,服务提供商可以各自提供自己的具体实现。大家都熟知的 JDBC 中用的就是基于这种机制来发现驱动提供商,不管是 Oracle 也好,MySQL 也罢,在编写代码时都一样,只不过引用的 jar 包不同而已。后来这种理念也被运用于各种架构之中,比如 Dubbo、Eleasticsearch。

1.2 JDK SPI 的小栗子

SPI 的实现方式是将接口实现类的全限定名配置在文件中,由服务加载器读取配置文件,加载实现类。


了解了概念后,来看一个具体的例子。


1)定义一个接口


public interface Operation {        int operate(int num1, int num2);}
复制代码


2)写两个简单的实现


public class DivisionOperation implements Operation {        public int operate(int num1, int num2) {            System.out.println("run division operation");            return num1/num2;        }}
复制代码


3)添加一个配置文件


在 ClassPath 路径下添加一个配置文件,文件名字是接口的全限定类名,内容是实现类的全限定类名,多个实现类用换行符分隔。


目录结构


1578290509268050916.png


文件内容


com.api.impl.DivisionOperationcom.api.impl.PlusOperation
复制代码


4)测试程序


public class JavaSpiTest {    @Test    public void testOperation() throws Exception {        ServiceLoader operations = ServiceLoader.load(Operation.class);        operations.forEach(item->System.out.println("result: " + item.operate(2, 2)));    } }
复制代码


5)测试结果


run division operationresult:1run plus operationresult:4
复制代码

1.3 JDK SPI 的源码分析

例子很简单,实现的话,可以大胆猜测一下,看名字“ServiceLoader”应该就是用类加载器根据接口的类型加上配置文件里的具体实现名字将实现加载了进来。


接下来通过分析源码进一步了解其实现原理。

1.3.1 ServiceLoader 类

PREFIX 定义了加载路径,reload 方法初始化了 LazyIterator,LazyIterator 是加载的核心,真正实现了加载。加载的模式从名字上就可以看出,是懒加载的模式,只有当真正调用迭代时才会加载。


1578290519778011984.png

1.3.2 hasNextService 方法

LazyIterator 中的 hasNextService 方法负责加载配置文件和解析具体的实现类名。


1578290528891044303.png

1.3.3 nextService 方法

LazyIterator 中的 nextService 方法负责用反射加载实现类。


1578290536263070478.png


看完了源码,感觉这个代码是有优化空间的,实例化所有实现其实没啥必要,一来比较耗时,二来浪费资源。Dubbo 就没有使用 Java 原生的 SPI 机制,而是对其进行了增强,使其能够更好地满足需求。


本文转载自宜信技术学院公众号。


原文链接:http://college.creditease.cn/detail/345


2020-02-06 10:311411

评论

发布
暂无评论
发现更多内容

WordPress 常规设置

海拥(haiyong.site)

WordPress 6月月更

fomo3d区块链分红游戏系统开发(案例演示)

开发微hkkf5566

企业竞争利器——知识管理

小炮

GIT 小白的指令合集

甜甜的白桃

git 版本管理 6月月更

微软成为规模化敏捷组织的16个关键因素

ShineScrum

敏捷 谷歌 规模化敏捷

java培训 @Autowired 的实现原理

@零度

JAVA开发

知名巧克力全球召回,区块链帮你摆脱“甜蜜陷阱”

旺链科技

区块链 产业区块链 食品安全 食品溯源

Web Service进阶(五)SOAPBinding方式讲解

No Silver Bullet

6月月更 SOAPBinding

SAP 云平台 ABAP 编程环境的前世今生

汪子熙

Cloud 云平台 SAP abap 6月月更

springboot,vue,es,activiti数字知识库管理系统

金陵老街

Vue springboot ES Activiti 知识库

建木持续集成平台v2.4.1发布

Jianmu

DevOps CI/CD 开源项目 gitops 自动化运维

中兴新支点加入龙蜥社区,共建操作系统开源新生态

OpenAnolis小助手

开源 龙蜥社区 合作 CLA 中兴新支点

7 个 Flutter 开源项目,让你成为更好的 Flutter 开发者

坚果

6月月更

C#入门系列(七) -- 循环语句

陈言必行

C# 6月月更

PHP开发者福音,支持CRUD代码生成且前后分离的tp6+Vue3后台管理系统开源啦!

妙码生花

php typescript Vue3 thinkphp Pinia

Linux驱动开发_视频广告机开发、Linux进程编程介绍

DS小龙哥

6月月更

性能优化手记下篇之【计费】

鲸品堂

性能优化 运维

重点亦难点?三个案例看数据分类分级如何有效有序进行

美创科技

数据分类 数据安全

最全!即学即会 Serverless Devs 基础入门(上)

Serverless Devs

【网络编程知识】什么是Socket?概念及原理分析

呆呆敲代码的小Y

Junit 测试中如何对异常进行断言

HoneyMoose

AssertJ 的异常(Exception )断言

HoneyMoose

探究Presto SQL引擎(3)-代码生成

vivo互联网技术

sql presto antlr4

spring4.1.8初始化源码学习三部曲之一:AbstractApplicationContext构造方法

程序员欣宸

Java spring 6月月更

浅谈JavaScript原型和原型链

大熊G

JavaScript 前端 6月月更

【100个 Unity踩坑小知识点】| Unity中的 Development build 详细解析

呆呆敲代码的小Y

如何使用物联网低代码平台进行模型管理?

AIRIOT

物联网 低代码开发

【Python技能树共建】字符串方法

梦想橡皮擦

6月月更

软件设计本质

GalaxyCreater

架构 设计模式 架构师 系统 软件设计

Fabric.js 精简输出的JSON🎫

德育处主任

FabricJS 6月月更

Dubbo源码解析之SPI(一):扩展类的加载过程(上)_区块链_郑祥斌_InfoQ精选文章