产品战略专家梁宁确认出席AICon北京站,分享AI时代下的商业逻辑与产品需求 了解详情
写点什么

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:311299

评论

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

网络攻防学习笔记 Day59

穿过生命散发芬芳

网络攻防 6月日更

前端面试中有趣的题目(一)

空城机

JavaScript 大前端 6月日更

「2021中国峰会同行记」第一回 | 与埃森哲一同追溯技术合力的本源

亚马逊云科技 (Amazon Web Services)

「2021中国峰会同行记」第二回 | 探索店匠从0到1出海的技术密码

亚马逊云科技 (Amazon Web Services)

领域驱动设计101 - 模块

luojiahu

领域驱动设计 DDD

lockSupport怎么玩

卢卡多多

锁机制 6月日更

python 连接钉钉传输工作数据监控

百里丶落云

德勤基于Amazon WAF 云原生安全服务为客户交付价值

亚马逊云科技 (Amazon Web Services)

迪士尼将亚马逊云科技作为首选的公有云基础设施供应商,支持 Disney+ 全球扩展

亚马逊云科技 (Amazon Web Services)

我是如何用 ThreadLocal 虐面试官的?

陈皮的JavaLib

Java 面试 多线程 ThreadLocal

详解Redis主从复制原理

蘑菇睡不着

Java redis

过一过Java“锁”事

CodeWithBuff

Java 并发 同步

快手封停多个内容侵权账号:如何严打短视频内容侵权行为

石头IT视角

人工智能应用架构的思考

金科优源汇

三个维度,透视5G价值的持续点亮之旅

脑极体

ZooKeeper实战

CodeWithBuff

Java zookeeper

如果非要在多线程中使用 ArrayList 会发生什么?(第二篇)

看山

Java 并发编程

Rust从0到1-函数式编程-迭代器

rust 函数式编程 Iterator 迭代器

【源码篇】Flutter Provider的另一面(万字图文+插件)

小呆呆666

flutter ios android 大前端

Linux之less命令

入门小站

Linux

[译] R8 优化: Lambda Groups

Antway

6月日更

推荐一个MySQL宝藏网站

Simon

MySQL 网站

如何设计恒流源输出电路?

不脱发的程序猿

嵌入式 电路设计 硬件研发 恒流源输出电路

成为你想要看到的改变,首先就是让正确的事情持续的发生。

叶小鍵

密码学系列之:twofish对称密钥分组算法

程序那些事

加密解密 密码学 程序那些事

建信金科大咖访谈:地方特色产业互联网建设思考与实践

金科优源汇

【源码篇】Flutter Bloc背后的思想,一篇纠结的文章

小呆呆666

flutter ios android 大前端

毕业论文被不小心删除了,有什么方法可以恢复?

淋雨

EasyRecovery 文件恢复 硬盘数据恢复

谈一谈Java的网络编程

CodeWithBuff

Java 网络io

研发管理工具 ONES 完成3亿人民币 B1 B2 轮融资,继续领跑研发管理赛道

万事ONES

项目管理 融资 研发管理工具 ONES

数据结构——顺序栈

若尘

数据结构 6月日更

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