11.Dubbo的适配器原理

2020-09-08  本文已影响0人  山海树

适配器模式通过定义一个新的接口(对要实现的功能加以抽象),和一个实现该接口的Adapter(适配器)类来透明地调用外部组件。这样替换外部组件时,最多只要修改几个Adapter类就可以了,其他源代码都不会受到影响。

从上面的适配器模式定义可以看出,所谓的适配器模式是针对一个接口,通过一个实现类Adapter来动态的替换具体需要的实现类。

在Dubbo中由于几乎所有的功能点都是由SPI来实现的,因此不可避免的产生的大量的接口和其对应的实现类,因此Dubbo采用适配器模式,来选择具体的业务操作室需要用的的真正的实现类。

用Protocol接口来说
在serviceConfig.export()的时候,Dubbo会根据动态编译技术来为Protocol生成一个Protcol$Adaptive的实例对象,该对象是实现了Protocol,其中的export()方法,通过获取Dubbo的URL的protoclo的值,来确定需要用到的具体的实现,

serviceConfig.export()->protocol.export()->protocol$Adaptive.export()->protocolImpl.export()->打开netty监听,向注册中心发布服务的操作。

因此在调用Protocol.export()的时候就变成通过适配器来调用真正的实现 的export()方法。

生成的Protocol代码

package org.apache.dubbo.rpc;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
  public void destroy()  {
          throw new UnsupportedOperationException("The method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
  }
  public int getDefaultPort()  {
           throw new UnsupportedOperationException("The method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
  }
  public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {
         if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
         if (arg0.getUrl() == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
         org.apache.dubbo.common.URL url = arg0.getUrl();
         String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
         if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");
         org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
        return extension.export(arg0);
  }
  public org.apache.dubbo.rpc.Invoker refer(java.lang.Class arg0, org.apache.dubbo.common.URL arg1) throws org.apache.dubbo.rpc.RpcException {
        if (arg1 == null) throw new IllegalArgumentException("url == null");
        org.apache.dubbo.common.URL url = arg1;
        String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
        if(extName == null) throw new IllegalStateException("Failed to get extension     (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");
        org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
        return extension.refer(arg0, arg1);
  }
}

(如果想看到别的SPI的Adaptive可以通过断点查看)


image.png

Dubbo中,会给每一个SPI扩展接口都进行此操作

上一篇下一篇

猜你喜欢

热点阅读