• Dubbo的SPI可扩展机制的源码分析


             Dubbo的代码的版本是2.7.0

           在看Dubbo源码的时候,总是出现下面的代码去加载一个类。 

              然后,看一下ProxyFactory这个类名上了加了一个注解。,

               

           这里以ServiceConfig里的ProxyFactory为例,这里就是今天所要讲的Dubbo的SPI机制, 通过ExtensionLoader这个类去实现的。

                 

             这里最主要的的ETENTION_LOADERS是保存扩展点类和对应ExtensionLoader的的映射, EXTENSION_INSTANCES是缓存扩展类和反射实例化的映射,

           getExtensionLoader函数,出入扩展类,如果没有,则放入IINSTENSION_LOADERS里面。映射的value是ExtensionLoader对象,可以看到新建的ExtensioLoader的扩展类

    不是ExtensionFactory,则还是会调用ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()方法,来加载adaptive的扩展类。

        然后,getAdaptiveExtension的,通过cacheAdaptiveExtension的get方法,  这里可以二次判断来防止的并发的操作。

              因为开始都为空,createAdativeExtension的函数创建一个扩展点的对象。

            然后调用getAdaptiveExtensionClass函数去加载扩展类,

        首先是通过  getExtensionClasses函数,获取扩展点的类

        因为开始都是空的,所以出事调用时候,会调用loadExtensionClasses函数,去加载所有的扩展类,

      

             前面是获取@SPI注解的值,然后loadDirectoy方法去加载项目下 META-INF/dubbo/internal/,META-INF/dubbo/, META-INF/services/

               这里就可以看出META-IN这下面的是都是扩展点的配置。

      

              这里是利用classloade加载class的,还调用loaderResource就是I利用Class.forName去加载对应的类了。

        加载完所有的扩展类后, 初始cacheAdaptiveClass为空,则创建createAdaptiveExtensionClass方法。

       这里首先看一下,createAdapativeExtensionClassCode动态生成的代码,从下面可以看出它生成的类名=扩展类+$Adaptive,实现扩展类的接口,并且找到ClassLoader,并且加载ExtensionLoader的Complier,去编译生成的代码,并且加载到JVM,得到一个Class.

    package org.apache.dubbo.rpc;
    import org.apache.dubbo.common.extension.ExtensionLoader;
    
    public class ProxyFactory$Adaptive implements org.apache.dubbo.rpc.ProxyFactory {
    private static final org.apache.dubbo.common.logger.Logger logger = org.apache.dubbo.common.logger.LoggerFactory.getLogger(ExtensionLoader.class);
    private java.util.concurrent.atomic.AtomicInteger count = new java.util.concurrent.atomic.AtomicInteger(0);
    
    public org.apache.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, org.apache.dubbo.common.URL arg2) throws org.apache.dubbo.rpc.RpcException {
    if (arg2 == null) throw new IllegalArgumentException("url == null");
    org.apache.dubbo.common.URL url = arg2;
    String extName = url.getParameter("proxy", "javassist");
    if(extName == null) throw new IllegalStateException("Fail to get extension(org.apache.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
    org.apache.dubbo.rpc.ProxyFactory extension = null;
     try {
    extension = (org.apache.dubbo.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension(extName);
    }catch(Exception e){
    if (count.incrementAndGet() == 1) {
    logger.warn("Failed to find extension named " + extName + " for type org.apache.dubbo.rpc.ProxyFactory, will use default extension javassist instead.", e);
    }
    extension = (org.apache.dubbo.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension("javassist");
    }
    return extension.getInvoker(arg0, arg1, arg2);
    }
    public java.lang.Object getProxy(org.apache.dubbo.rpc.Invoker arg0, boolean arg1) 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.getParameter("proxy", "javassist");
    if(extName == null) throw new IllegalStateException("Fail to get extension(org.apache.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
    org.apache.dubbo.rpc.ProxyFactory extension = null;
     try {
    extension = (org.apache.dubbo.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension(extName);
    }catch(Exception e){
    if (count.incrementAndGet() == 1) {
    logger.warn("Failed to find extension named " + extName + " for type org.apache.dubbo.rpc.ProxyFactory, will use default extension javassist instead.", e);
    }
    extension = (org.apache.dubbo.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension("javassist");
    }
    return extension.getProxy(arg0, arg1);
    }
    public java.lang.Object getProxy(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.getParameter("proxy", "javassist");
    if(extName == null) throw new IllegalStateException("Fail to get extension(org.apache.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
    org.apache.dubbo.rpc.ProxyFactory extension = null;
     try {
    extension = (org.apache.dubbo.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension(extName);
    }catch(Exception e){
    if (count.incrementAndGet() == 1) {
    logger.warn("Failed to find extension named " + extName + " for type org.apache.dubbo.rpc.ProxyFactory, will use default extension javassist instead.", e);
    }
    extension = (org.apache.dubbo.rpc.ProxyFactory).getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension("javassist");
    }
    return extension.getProxy(arg0);
    }
    }
    

     总结:

           本次对Dubbo 的SPI机制的一点粗略的理解。

  • 相关阅读:
    Eclipse_debug异常_Source not found
    Mybatis异常_01_Invalid bound statement (not found)
    [转]Eclipse快捷键_01_常用快捷键汇总
    PL/SQL学习笔记_03_存储函数与存储过程
    PL/SQL学习笔记_02_游标
    PL/SQL学习笔记_01_基础:变量、流程控制
    Oracle学习笔记_05_分组函数
    博客园_01_为博客园添加目录的方法总结
    Oracle学习笔记_04_多表查询
    Oracle学习笔记_03_单行函数
  • 原文地址:https://www.cnblogs.com/xjz1842/p/9876210.html
Copyright © 2020-2023  润新知