zoukankan      html  css  js  c++  java
  • 20211012 Dubbo 的 SPI 和 Adaptive

    准备工作

    定义服务接口:

    package com.lagou.service;
    
    import org.apache.dubbo.common.URL;
    import org.apache.dubbo.common.extension.Adaptive;
    import org.apache.dubbo.common.extension.SPI;
    
    @SPI("human")
    public interface HelloService {
        String sayHello();
    
        @Adaptive
        String sayHello(URL url);
    }
    

    两个接口实现类:

    package com.lagou.service.impl;
    
    import com.lagou.service.HelloService;
    import org.apache.dubbo.common.URL;
    
    public class DogHelloService implements HelloService{
        @Override
        public String sayHello() {
            return "wang wang";
        }
    
        @Override
        public String sayHello(URL url) {
            return "wang url";
        }
    }
    
    package com.lagou.service.impl;
    
    import com.lagou.service.HelloService;
    import org.apache.dubbo.common.URL;
    
    public class HumanHelloService implements HelloService{
        @Override
        public String sayHello() {
            return "hello 你好";
        }
    
        @Override
        public String sayHello(URL url) {
            return  "hello url";
        }
    }
    

    SPI

    定义 SPI 配置文件:META-INF/dubbo/com.lagou.service.HelloService

    human=com.lagou.service.impl.HumanHelloService
    dog=com.lagou.service.impl.DogHelloService
    

    SPI 调用:

    package com.lagou;
    
    import com.lagou.service.HelloService;
    import org.apache.dubbo.common.extension.ExtensionLoader;
    
    import java.util.Set;
    
    public class DubboSpiMain {
        public static void main(String[] args) {
            // 获取扩展加载器
            ExtensionLoader<HelloService> extensionLoader = ExtensionLoader.getExtensionLoader(HelloService.class);
            // 遍历所有的支持的扩展点 META-INF.dubbo
            Set<String> extensions = extensionLoader.getSupportedExtensions();
            for (String extension : extensions) {
                String result = extensionLoader.getExtension(extension).sayHello();
                System.out.println(result);
            }
    
            System.out.println("=================");
    
            // 指定调用
            System.out.println(extensionLoader.getExtension("human").sayHello());
    
        }
    }
    

    Adaptive

    public class DubboAdaptiveMain {
        public static void main(String[] args) {
            URL url = URL.valueOf("test://localhost/hello?hello.service=dog");
            ExtensionLoader<HelloService> extensionLoader = ExtensionLoader.getExtensionLoader(HelloService.class);
            HelloService adaptiveExtension = extensionLoader.getAdaptiveExtension();
            String msg = adaptiveExtension.sayHello(url);
            System.out.println(msg);
        }
    }
    

    分析源码

    生成 Adaptive 类代码:org.apache.dubbo.common.extension.ExtensionLoader#createAdaptiveExtensionClass

    以上面的接口为例,生成的代码是:

    package com.lagou.service;
    
    import org.apache.dubbo.common.extension.ExtensionLoader;
    
    public class HelloService$Adaptive implements com.lagou.service.HelloService {
        public java.lang.String sayHello() {
            throw new UnsupportedOperationException(
                    "The method public abstract java.lang.String com.lagou.service.HelloService.sayHello() of interface com.lagou.service.HelloService is not adaptive method!");
        }
    
        public java.lang.String sayHello(org.apache.dubbo.common.URL arg0) {
            if (arg0 == null)
                throw new IllegalArgumentException("url == null");
            org.apache.dubbo.common.URL url = arg0;
            String extName = url.getParameter("hello.service", "human");
            if (extName == null)
                throw new IllegalStateException("Failed to get extension (com.lagou.service.HelloService) name from url ("
                        + url.toString() + ") use keys([hello.service])");
            com.lagou.service.HelloService extension = (com.lagou.service.HelloService) ExtensionLoader
                    .getExtensionLoader(com.lagou.service.HelloService.class).getExtension(extName);
            return extension.sayHello(arg0);
        }
    }
    

    可以看出,Adaptive 类只是做了一个转发,实际还是 SPI 调用,这里转发的工作是获得 SPI 的 key ,也就是按照一定的规则选择 SPI:

    • 如果指定了 @Adaptivevalue ,根据此 value 寻找 URL 上的参数
    • 如果接口方法上未指定 @Adaptivevalue ,会根据类名称按照规则指定,例如 HelloService 默认为 hello.service
    • 如果 URL 的参数上没有 @Adaptive 指定的 key ,使用 @SPIvalue 作为默认
  • 相关阅读:
    iOS取消按钮点击时的动画效果
    iOS实现简书和知乎的上滑隐藏导航栏下拉显示导航栏效果
    idea添加Jetty时提示JMX module is not included
    人的差别在于业余时间,而一个人的命运决定于晚上8点到10点之间
    如果做好一个出色的程序员
    阅读的技巧
    JQuery返回布尔值Is()方法.条件判断
    Javascript遍历each与map
    html5Canvas绘制弧线(圆形)
    jQuery插件背景滑动菜单(第二次自已偿试写插件)
  • 原文地址:https://www.cnblogs.com/huangwenjie/p/15396335.html
Copyright © 2011-2022 走看看