写点什么

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

评论

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

聊聊接口性能优化的11个小技巧

苏三说技术

性能优化

哪吒 D1-H 测试 microbench

贾献华

7月月更

ORIGYN基金会正式启动$OGY Staking,引领新一轮生态利好

鳄鱼视界

Bootstrap快捷开发【前端Bootstrap框架】

恒山其若陋兮

7月月更

IPv4地址已经完全耗尽,互联网还能正常运转,NAT是最大功臣!

wljslmz

NAT ipv4 网络技术 7月月更

数据质量:数据治理的核心

奔向架构师

数据治理 7月月更

怎样设计产品帮助中心?以下几点不可忽视

Baklib

高并发下如何保证数据库和缓存双写一致性?

苏三说技术

MySQL redis

互联网协议之 IPFS

devpoint

区块链 IPFS Filecoin 7月月更

【函数式编程实战】(六) Stream高并发实战

小明Java问道之路

Java stream 高并发 7月月更 签约计划第三季

以寡治众各个击破,超大文件分片上传之构建基于Vue.js3.0+Ant-desgin+Tornado6纯异步IO高效写入服务

刘悦的技术博客

tornado 异步 数据分片 Vue 3 文件上传

高效生成接口文档好方法

Xd

数据库 接口测试

JS作用域与作用域链

程序员海军

7月月更

当AI邂逅生命健康,华为云为他们搭建三座桥

脑极体

动画曲线天天用,你能自己整一个吗?看完这篇你就会了!

岛上码农

flutter ios 前端 安卓开发 签约计划第三季

【帮助中心】为您的客户提供自助服务的核心选项

Geek_da0866

人人可参与开源活动正式上线,诚邀您来体验!

阿里巴巴云原生

阿里云 开源 云原生 龙蜥社区

ES6---4个非常好用的运算符(??、??=、?.、?:)

Java学术趴

7月日更

栈与Stack类

未见花闻

7月月更

聊聊Java中代码优化的30个小技巧

苏三说技术

【刷题记录】21. 合并两个有序链表

WangNing

7月月更

Baklib:制作优秀的产品说明手册

Baklib

Docker 搭建 Redis Cluster集群

宁在春

redis Docker 集群 7月月更

性能调试 -- Chrome Performance

空城机

chrome Performance 7月月更

依法严厉打击违规自媒体运营者:净化自媒体行业迫在眉睫

石头IT视角

ThreadLocal夺命11连问

苏三说技术

多线程

聊聊sql优化的15个小技巧

苏三说技术

sql SQL优化

信息安全建设原则指导

穿过生命散发芬芳

7月月更 信息安全建设

这次龙蜥展区玩的新花样,看看是谁的 DNA 动了?

OpenAnolis小助手

龙蜥社区 北京 开放原子全球开源峰会 7 月 27 日-29 日 分论坛

git merge 不为人知的秘密

蛋先生DX

git merge 最长公共子序列 签约计划第三季 three-way 3-way

伺服驱动器在机器人上的研究与应用

优必选科技

机器人

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