zoukankan      html  css  js  c++  java
  • Dubbo扩展机制(一)SPI

    SPI 全称为 Service Provider Interface,是一种服务发现机制
     
    一、Java SPI
    从上面可以看出Java中的SPI最大的缺点是会加载一些不必要的组件。
     
    二、Dubbo SPI
    (1)基本原理
    Dubbo在某个接口上加上@SPI注解后,表明该接口为可扩展接口
    ExtensionLoader类是扩展加载器,这是dubbo实现SPI扩展机制等核心,几乎所有实现的逻辑都被封装在ExtensionLoader中
     
    示例代码
    @SPI("alipay")
    public interface PayService {
        void pay(double price);
    }
    
    public class AlipayService implements PayService {
        @Override
        public void pay(double price) {
            System.out.println("使用支付宝支付" + price +  "元");
        }
    }
    
    public class WechatPayService implements PayService {
        public void pay(double price) {
            System.out.println("使用微信支付" + price +  "元");
        }
    }
    /resources/META-INF/services/目录下有个文件com.test.PayService,内容如下:
    wechatPay = com.test.WechatPayService
    alipay = com.test.AlipayService
    测试
    public static void main(String[] args) {
        ExtensionLoader<PayService> extensionLoader = ExtensionLoader.getExtensionLoader(PayService.class);
    
        PayService wechatPay = extensionLoader.getExtension("wechatPay");
        wechatPay.pay(20);
    
        PayService alipay = extensionLoader.getExtension("alipay");
        alipay.pay(20);
    }
     
    (2)Dubbo中的使用(间接调用)
    Dubbo 就是通过 SPI 机制加载所有的组件,但是Dubbo中一般不直接通过extensionLoader.getExtension("alipay") 方法来调用,而是动态适配的,即通过Adaptive实现,下个章节再讲。下面以ProxyFactory为例
    ProxyFactory是一个接口,在其接口上使用了@SPI注解,并默认赋值为javassist
    @SPI("javassist") // 默认
    public interface ProxyFactory {...}
    在 /dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal 目录下有一个com.alibaba.dubbo.rpc.ProxyFactory 文件,文件内容如下
    stub=com.alibaba.dubbo.rpc.proxy.wrapper.StubProxyFactoryWrapper
    jdk=com.alibaba.dubbo.rpc.proxy.jdk.JdkProxyFactory
    javassist=com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory
    Dubbo间接使用的地方,如ReferenceConfig类创建代理对象的过程
    public class ReferenceConfig<T> extends AbstractReferenceConfig {
        private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
        ...
        private T createProxy(Map<String, String> map) {
            ...
            // 该方法的最后一行
            return (T) proxyFactory.getProxy(invoker);
        }
         ...   
    }
    proxyFactory 会通过ExtensionLoader,再调用getAdaptiveExtension方法,会生成一个ProxyFactory$Adaptive类。
    public java.lang.Object getProxy(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException {
        if (arg0 == null) 
            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null) 
            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
        com.alibaba.dubbo.common.URL url = arg0.getUrl();
        // 1.从 URL 中获取指定的SPI的扩展名称,proxy
        String extName = url.getParameter("proxy", "javassist");
        if(extName == null) 
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" 
                                            + url.toString() + ") use keys([proxy])");
        // 2.通过 SPI 加载具体的实现类
        com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory)ExtensionLoader
            .getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);
        // 3.调用目标方法
        return extension.getProxy(arg0);
    }
    步骤2则是真正调用的地方。
     
  • 相关阅读:
    javaScript函数参数
    python创建pipenv虚拟环境
    信立温度模块解析(模拟量)
    Modbus Poll使用
    云智网关连接
    python中创建virtualenv虚拟环境
    python环境变量配置
    Mysql数据库环境变量配置
    github中创建远程仓库
    python解释器下载
  • 原文地址:https://www.cnblogs.com/caoxb/p/13140318.html
Copyright © 2011-2022 走看看