我是靠谱客的博主 如意枕头,最近开发中收集的这篇文章主要介绍dubbo学习篇之dubbo内核解析(一)SPIdubbo的内核,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

dubbo内核解析

  • dubbo的内核
    • SPI
      • JDK中的SPI
        • JDK中SPI的规范
        • JDK中SPI的实现
          • 定义SPI服务接口
          • 定义服务实现类
          • 按照SPI规范编写服务提供者配置文件
          • 编写main方法来进行服务调用
        • JDK中SPI的不足
      • dubbo中的SPI
        • dubbo中SPI的规范
        • dubbo中SPI的使用
          • 定义SPI服务接口
          • 定义服务实现类
          • 按照dubbo的SPI规范编写服务提供者配置文件
          • 编写main方法来进行服务调用

dubbo的内核

dubbo所有功能都是基于dubbo内核之上完成的,dubbo内核由四部分构成,分别为SPI,Adaptive,Wrapper,Activate。
而dubbo的内核设计原则,也是我们所熟悉的aop,ioc与动态编译compiler,这些称之为dubbo的内核原理。

SPI

SPI,Service Provider Interface服务提供者接口,是一种服务发现机制。
SPI的存在使得服务提供者与使用者之间实现了解耦。

JDK中的SPI

JDK中SPI的规范

  • 接口名:没有限制
  • 实现类名:没有限制
  • 提供者配置文件路径:限定为META-INF/services
  • 提供者配置文件名称:接口的全限定类名
  • 提供者配置文件内容:接口的所有实现类的全限定类名,一个类名占一行

JDK中SPI的实现

定义SPI服务接口
package com.demo.service;

public interface DemoService {

    String hello();
}

定义服务实现类
package com.demo.service.impl;

import com.demo.service.DemoService;

public class OneDemoService implements DemoService {
    public String hello() {
        return "one";
    }
}

package com.demo.service.impl;

import com.demo.service.DemoService;

public class TwoDemoService implements DemoService {
    public String hello() {
        return "two";
    }
}

按照SPI规范编写服务提供者配置文件

在这里插入图片描述

编写main方法来进行服务调用
package com.demo.service;

import java.util.Iterator;
import java.util.ServiceLoader;

public class MainClass {
    public static void main(String[] args) {
        ServiceLoader<DemoService> loader = ServiceLoader.load(DemoService.class);

        Iterator<DemoService> iterator = loader.iterator();

        while(iterator.hasNext()) {
            DemoService service = iterator.next();
            System.out.println(service.hello());
        }
    }
}

查看一下运行结果
在这里插入图片描述
观察这个配置结果我们会发现,ServiceLoader方法会按照我们事先配置好的提供者配置文件来调用实现类。

JDK中SPI的不足

通过上面的例子我们可以观察出来,我们没有办法具体到调用哪一个实现类,比如我只想调用OneDemoService是做不到的

dubbo中的SPI

dubbo源码中SPI使用的相当频繁,可以说SPI是dubbo内核中的内核。

dubbo中SPI的规范

  • 接口名:没有限制
  • 实现类名:在接口名前添加一个用于表示自身功能的“标识前辍”字符串
  • 提供者配置文件路径:在依次查找的目录为
    META-INF/dubbo/internal
    META-INF/dubbo
    META-INF/services
    这一点可以参考源码ExtensionLoader.java 631-643
    // synchronized in getExtensionClasses
    private Map<String, Class<?>> loadExtensionClasses() {
        cacheDefaultExtensionName();

        Map<String, Class<?>> extensionClasses = new HashMap<>();
        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName());
        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
        loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName());
        loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName());
        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
        return extensionClasses;
    }
  • 提供者配置文件名称:接口的全限定性类名,无需扩展名
  • 提供者配置文件内容:文件的内容为 key=value 形式,value 为该接口的实现类的全限类
    性类名,key 可以随意,但一般为该实现类的“标识前辍”(首字母小写)。一个类名占
    一行。
  • 提供者加载:ExtensionLoader 类相当于 JDK SPI 中的 ServiceLoader 类,用于加载提供者
    配置文件中指定的实现类,并创建相应的实例。

dubbo中SPI的使用

定义SPI服务接口

需要引用dubbo的依赖

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

/**
 * 该注解为标识注解,代表该类为SPI
 * 且value值代表默认提供者为服务提供者文件中定义为alipay的服务实现类
 */
@SPI("alipay")
public interface Order {
    void pay();
}

定义服务实现类
public class AlipayOrder implements Order {
    @Override
    public void pay() {
        System.out.println("使用支付宝支付");
    }
}
public class WechatOrder implements Order {
    @Override
    public void pay() {
        System.out.println("使用微信支付");
    }
}
按照dubbo的SPI规范编写服务提供者配置文件

在这里插入图片描述

编写main方法来进行服务调用
package com.dubbospi.service;

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

public class MainClass {
    public static void main(String[] args) {
        ExtensionLoader<Order> loader = ExtensionLoader.getExtensionLoader(Order.class);

        Order order = loader.getExtension("wechat");
        order.pay();
        Order order1 = loader.getDefaultExtension();
        order1.pay();
    }
}

执行结果如下
在这里插入图片描述

最后

以上就是如意枕头为你收集整理的dubbo学习篇之dubbo内核解析(一)SPIdubbo的内核的全部内容,希望文章能够帮你解决dubbo学习篇之dubbo内核解析(一)SPIdubbo的内核所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(59)

评论列表共有 0 条评论

立即
投稿
返回
顶部