dubbo源码阅读之-java spi, dubbo spi 和 Spring spi 到底有啥区别

这篇具有很好参考价值的文章主要介绍了dubbo源码阅读之-java spi, dubbo spi 和 Spring spi 到底有啥区别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

SPI

SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。
Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制。

Java SPI

案例

接口

public interface Hello {
    void say();
}

实现类

public class LiHello implements Hello{
    public void say() {
        System.out.println("li hello");
    }
}
public class ZhangHello implements Hello{
    public void say() {
        System.out.println("zhang hello");
    }
}

接口全限定名 作为文件名,实现类全限定名为内容
dubbo源码阅读之-java spi, dubbo spi 和 Spring spi 到底有啥区别
com.wfg.spi.javaspi.LiHello
com.wfg.spi.javaspi.ZhangHello

public class JavaSpi {
    public static void main(String[] args) {
        ServiceLoader<Hello> load = ServiceLoader.load(Hello.class);
        load.forEach(Hello::say);

    }
}

dubbo源码阅读之-java spi, dubbo spi 和 Spring spi 到底有啥区别

调用过程:
应用程序调用ServiceLoader.load方法,创建一个新的ServiceLoader,并实例化该类中的成员变量

应用程序通过迭代器接口获取对象实例,ServiceLoader先判断成员变量providers对象中(LinkedHashMap类型)是否有缓存实例对象,如果有缓存,直接返回。

如果没有缓存,执行类的装载,

优缺点

优点

使用 Java SPI 机制的优势是实现解耦,使得接口的定义与具体业务实现分离,而不是耦合在一起。应用进程可以根据实际业务情况启用或替换具体组件。

缺点

  • 不能按需加载。虽然 ServiceLoader 做了延迟载入,但是基本只能通过遍历全部获取,也就是接口的实现类得全部载入并实例化一遍。如果你并不想用某些实现类,或者某些类实例化很耗时,它也被载入并实例化了,这就造成了浪费。

  • 获取某个实现类的方式不够灵活,只能通过 Iterator 形式获取,不能根据某个参数来获取对应的实现类。

  • 多个并发多线程使用 ServiceLoader 类的实例是不安全的。

  • 加载不到实现类时抛出并不是真正原因的异常,错误很难定位。

Spring SPI

Dubbo SPI

概述

Dubbo 并未使用 Java SPI,而是重新实现了一套功能更强的 SPI 机制。Dubbo SPI 的相关逻辑被封装在了 ExtensionLoader 类中,通过 ExtensionLoader,我们可以加载指定的实现类。

简单案例

此时只写和java不同的地方
接口上添加@SPI 注解

@SPI("hello")
public interface Hello {
    void say();
}

配置内容是键值对方式,因此可以根据key获取实现类

dubbo会从四个目录读取文件META-INF/dubbo/internal/ 、META-INF/dubbo/ 、META-INF/services/、META-INF/dubbo/external/,文件名为接口的全限定名,内容为键值对,键为短名称(可以理解为spring中的对象的名称),值为实现类

h1=com.wfg.spi.dubbospi.LiHello
h2=com.wfg.spi.dubbospi.ZhangHello
public class DubboSpi {

    public static void main(String[] args) {
        ExtensionLoader<Hello> extensionLoader =
                ExtensionLoader.getExtensionLoader(Hello.class);
        Hello h1 = extensionLoader.getExtension("h1");
        h1.say();
        Hello h2 = extensionLoader.getExtension("h2");
        h2.say();
    }
}

Dubbo SPI 除了支持按需加载接口实现类,还增加了 IOC 和 AOP 等特性,这些特性将会在接下来的源码分析章节中一一进行介绍。

aop 案例

@SPI
public interface Car {

    public String getColor();
}
public class BackCar implements Car{
    @Override
    public String getColor() {
        System.out.println("黑色车");
        return "red";
    }
}
public class RedCar implements Car{
    @Override
    public String getColor() {
        System.out.println("红色车");
        return "red";
    }
}
public class CarMain {

    public static void main(String[] args) {
        ExtensionLoader<Car> extensionLoader =
                ExtensionLoader.getExtensionLoader(Car.class);
        Car red = extensionLoader.getExtension("red");
        red.getColor();

        Car back = extensionLoader.getExtension("back");
        back.getColor();

//        Car wrapper = extensionLoader.getExtension("wrapper");
//        wrapper.getColor();
    }
}

上面是最基本的用法,我们下面增加一个包装类

public class CarWrapper implements Car {

    private Car car;

    public CarWrapper(Car car) {
        this.car = car;
    }

    @Override
    public String getColor() {
        System.out.println("carWrapper before");
        String color = car.getColor();
        System.out.println("carWrapper after");
        return color;
    }
}

其实包装类和普通的实现类没有太大的区别,是通过一个构造方法注入了一个继承的接口类,
运行效果如下:
dubbo源码阅读之-java spi, dubbo spi 和 Spring spi 到底有啥区别
这个还是需要写的

red=com.wfg.dubbo.demo.spi.RedCar
back=com.wfg.dubbo.demo.spi.BackCar
wrapper=com.wfg.dubbo.demo.spi.CarWrapper

ioc 案例

上面我们可以看到已经实现了aop, aop是靠的构造方法实现, 接下来用的ioc是靠的set方法实现的;

主要的注解: @Adaptive

代码修改如下

@SPI
public interface Car {
    @Adaptive(value = "carType")
    public String getColor(URL url);
}
public class BackCar implements Car {
    @Override
    public String getColor(URL url) {
        System.out.println("黑色车");
        return "back";
    }
}
public class RedCar implements Car {

    @Override
    public String getColor(URL url) {
        System.out.println("红色车");
        return "red";
    }
}

修改点:1. 参数增加URL 参数, 也可以是POJO的一个属性
2. 方法上增加@Adaptive 注解

下面我们在用扩展点实现一个Driver的扩展点:

@SPI
public interface Driver {

    public void driverCar(URL url);
}
public class Trucker implements Driver {
    private Car car;
    // dubbo 的ioc 是靠set 方法注入的
    //但是这个实例又是如何选择的
    public void setCar(Car car) {
        this.car = car;
    }
    @Override
    public void driverCar(URL url) {
        System.out.println("Trucker =====");
        car.getColor(url);
    }
}

Trucker 中注入一个Car 类型的属性, car.getColor(url); car的实例是在运行的时候动态赋值的

调用代码如下:

public class DriverMain {

    public static void main(String[] args) {
        ExtensionLoader<Driver> extensionLoader =
                ExtensionLoader.getExtensionLoader(Driver.class);
        Driver trucker = extensionLoader.getExtension("trucker");
        Map<String,String> map = new HashMap<>();
        map.put("carType","red");
        URL url = new URL("","",0,map);
        trucker.driverCar(url);
    }
}

这里靠的是URL 传参,识别出用哪个car的实例文章来源地址https://www.toymoban.com/news/detail-478785.html

源码分析

自己实现一个SPI

到了这里,关于dubbo源码阅读之-java spi, dubbo spi 和 Spring spi 到底有啥区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Dubbo源码篇06---SPI神秘的面纱---原理篇---上

    Dubbo源码篇06---SPI神秘的面纱---原理篇---上

    上一篇文章,Dubbo源码篇05—SPI神秘的面纱—使用篇带领大家过了一遍Dubbo SPI的机制和使用,本文我们来深入Dubbo源码,一览背后原理。 本文基于: Dubbo SPI机制解析 一文而做,简化原文源码篇幅,加以图画解释。 随着服务化的推广,网站对Dubbo服务框架的需求逐渐增多,Dub

    2024年02月07日
    浏览(12)
  • 趁同事上厕所的时间,看完了 Dubbo SPI 的源码,瞬间觉得 JDK SPI 不香了

    趁同事上厕所的时间,看完了 Dubbo SPI 的源码,瞬间觉得 JDK SPI 不香了

    👏作者简介:大家好,我是爱敲代码的小黄,独角兽企业的Java开发工程师,CSDN博客专家,阿里云专家博主 📕系列专栏:Java设计模式、Spring源码系列、Netty源码系列、Kafka源码系列、JUC源码系列、duubo源码系列 🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦

    2024年02月16日
    浏览(8)
  • 深入理解java和dubbo的SPI机制

    本质:将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。 java SPI:用来设计给服务提供商做插件使用的。基于策略模式来实现动态加载的机制。我们在程序只定义一个接口,具体的实现交个不同

    2024年02月08日
    浏览(7)
  • 实战系列(一)| Dubbo和Spring Cloud的区别,包含代码详解

    实战系列(一)| Dubbo和Spring Cloud的区别,包含代码详解

    Dubbo 和 Spring Cloud 都是微服务架构中的重要框架,但它们的定位和关注点不同。Dubbo 是阿里巴巴开源的一个高性能、轻量级的 RPC 框架,主要用于构建微服务之间的服务治理。而 Spring Cloud 是基于 Spring Boot 的一个微服务架构开发工具,它提供了一系列的开发工具和服务,帮助开

    2024年02月10日
    浏览(7)
  • 爬虫到底是什么呢?爬虫有啥用途呢?

    爬虫到底是什么呢?爬虫有啥用途呢?

    爬虫技术 爬虫主要用于网络网页,又称网络爬虫和网络蜘蛛,可以自动浏览网络中的信息或一种网络机器人。它们广泛应用于互联网搜索引擎或其他类似的网站,以获取或更新这些网站的内容和检索方法。它们可以自动收集所有可访问的页面内容,以便程序进行下一步处理。

    2024年02月12日
    浏览(5)
  • Web3到底是什么?和区块链有啥关系?

    Web3到底是什么?和区块链有啥关系?

    今年4、5月的时候, web3在微信指数中的趋势数据,一度超过了区块链。 从2021年12月份开始,web3这个词突然出圈,进入传统互联网,然后开始蔓延火爆。   从最近互联网圈的融资情况和创业动态看,似乎传统VC们都在号召“ALL in  Web3”。 那么Web3到底是什么?未来会如何发展

    2024年01月22日
    浏览(13)
  • Dubbo的SPI机制

    Dubbo的SPI机制

    加载扩展点配置 :Dubbo SPI首先会加载所有的扩展点配置,这些配置通常是在META-INF/dubbo目录下的properties文件中定义的。每个配置文件的名称就是扩展点接口的全限定名,文件内容是扩展点实现的键值对,键是扩展点的名称,值是扩展点实现类的全限定名。 创建扩展点实例 :

    2024年01月23日
    浏览(6)
  • Apache Dubbo的@SPI接口应用

    记录 :472 场景 :使用Apache Dubbo的@SPI接口加载实现类搭建框架。 版本 :JDK 1.8,dubbo-common-3.0.0。 SPI全称Service Provider Interface。 1.基础 1.1引用依赖 1.2应用 (1)使用@SPI注解作用在自定义接口com.hub.example.pf.adapter.IPfDataAdapter。 (2)业务类TCityAdapterImpl、TProvinceAdapterImpl等实现接口IPfDat

    2024年02月07日
    浏览(9)
  • 到了这个年纪,就应该阅读Spring源码了,源码阅读指南-编译加运行

    到了这个年纪,就应该阅读Spring源码了,源码阅读指南-编译加运行

    Spring的源码地址 https://github.com/spring-projects/spring-framework 我们先把他clone下来 没梯子的话多clone几遍就好了 我们这里使用5.x的版本 设置里面gradle设置按照如下图设置即可 😊gradle介绍(插叙手法) 由于Spring源码都是使用Gradle来管理项目 按理来说我们gradle和maven类似,需要在本

    2023年04月09日
    浏览(16)
  • 服务器和电脑有啥区别?

    服务器和电脑有啥区别?

    服务器可以说是“高配的电脑”,两者都有CPU、硬盘、电源等基础硬件组成,但服务器和电脑也是有一定区别的,让小编带大家了解一下吧! #秋天生活图鉴# 1、稳定性需求不同:服务器是全年无休,需要高稳定性,很多时候服务器就只有一次开机机会,接着就要提供高强度

    2024年02月01日
    浏览(13)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包