Dubbo的SPI的分析

首先定義:

SPI:即Service Provider Interface,釋義爲服務提供接口

JDK SPI:Java的spi機制,是去掃描/META-INF/service/的接口名文件,並獲取文件中的值。以mysql的驅動類來做爲案例。

打開對應文件:

ServiceLoader<Command> serviceLoader=ServiceLoader.load(Command.class); 
for(Command command:serviceLoader){ 
   // 循環執行
   command.execute();  
}  

這裏用到了類的上下文加載器進行加載。
Java通過迭代器,循環加載對應文件中的類。

dubbo SPI:
通過ExtensionLoader.getExtension(String name)實現路徑:

getExtensionLoader(Class<T> type) 就是爲該接口 new 一個 ExtensionLoader,然後緩存起來。



getAdaptiveExtension() 獲取一個擴展類,如果 @Adaptive 註解在類上就是一個裝飾類;如果註解在方法上就是一個動態代理類,例如 Protocol$Adaptive 對象。



getExtension(String name) 獲取一個指定對象。
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
    // 刪除部分非空判斷代碼// 先判斷擴展類是否已經存在
    ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
    if (loader == null) 
        // 緩存 interface 對應的 dubbo spi 擴展加載類
        EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
        loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
    }
    return loader;
}private ExtensionLoader(Class<?> type) {
        this.type = type;
    // 創建工廠,即 dubbo 的 IOC 輸出中心,兩個實現類 [SpiExtensionFactory,SpringExtensionFactory]
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }

 

public T getExtension(String name) {
    // 刪除部分代碼
    // 獲取一個實體類,其中持有一個 volatile 的 interface 實現類對象,保證內存可見性
    Holder<Object> holder = cachedInstances.get(name);
    if (holder == null) {
        cachedInstances.putIfAbsent(name, new Holder<Object>());
        holder = cachedInstances.get(name);
    }
    Object instance = holder.get();
    if (instance == null) {
        synchronized (holder) {
            instance = holder.get();
            if (instance == null) {
             // 創建一個 interface 的實例對象
                instance = createExtension(name);
                holder.set(instance);
            }
        }
    }
    return (T) instance;
}private T createExtension(String name) {
      // 獲取對應的 name 的 class 加載類
        Class<?> clazz = getExtensionClasses().get(name);
      // 省略部分代碼
        try {
            // 緩存對應是否存在
            T instance = (T) EXTENSION_INSTANCES.get(clazz);
            if (instance == null) {
                EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            // 注入對象
            injectExtension(instance);
            Set<Class<?>> wrapperClasses = cachedWrapperClasses;
            if (wrapperClasses != null && wrapperClasses.size() > 0) {
                for (Class<?> wrapperClass : wrapperClasses) {
                    // 構造器注入,,,IOC 
                    instance = injectExtension((T)  wrapperClass.getConstructor(type).newInstance(instance));
                }
            }
            return instance;
        } catch (Throwable t) {
            // 異常處理
        }
    }private T injectExtension(T instance) {
 try {
  if (objectFactory != null) {
   for (Method method : instance.getClass().getMethods()) {
     // 獲取方法名是 set 的屬性,進下屬性注入,,即 IOC 
                if (method.getName().startsWith("set")
      && method.getParameterTypes().length == 1
      && Modifier.isPublic(method.getModifiers())) {
     Class<?> pt = method.getParameterTypes()[0];
     try {
      String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
      Object object = objectFactory.getExtension(pt, property);
      if (object != null) {
       method.invoke(instance, object);
      }
     } catch (Exception e) {
      logger.error("fail to inject via method " + method.getName()
        + " of interface " + type.getName() + ": " + e.getMessage(), e);
     }
    }
   }
  }
 } catch (Exception e) {
  logger.error(e.getMessage(), e);
 }
 return instance;
}

ExtensionLoader.getExtensionLoader(Class type)#

 ExtensionLoader.getExtensionLoader(Container.class) -->this.type = type; -->objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); -->ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension() -->this.type = type; -->objectFactory =null;

getExtension(String name) 核心調用鏈如下#
getExtension(String name)
//指定對象緩存在cachedInstances;get出來的對象wrapper對象,例如protocol就ProtocolFilterWrapper和ProtocolListenerWrapper其中一個。

 -->createExtension(String name) -->getExtensionClasses() -->injectExtension(T instance)//dubbo的IOC反轉控制,就是從spi和spring裏面提取對象賦值。 -->objectFactory.getExtension(pt, property) -->SpiExtensionFactory.getExtension(type, name) -->ExtensionLoader.getExtensionLoader(type) -->loader.getAdaptiveExtension() -->SpringExtensionFactory.getExtension(type, name) -->context.getBean(name) -->injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance))//AOP的簡單設計

getAdaptiveExtension()#

   -->getAdaptiveExtension()//爲cachedAdaptiveInstance賦值 -->createAdaptiveExtension() -->getAdaptiveExtensionClass() -->getExtensionClasses()//爲cachedClasses 賦值 -->loadExtensionClasses() -->loadFile -->createAdaptiveExtensionClass()//自動生成和編譯一個動態的adpative類,這個類是一個代理類 -->ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension() -->compiler.compile(code, classLoader) -->injectExtension()//作用:進入IOC的反轉控制模式,實現了動態注入

總結

  • 1、dubbo 設計了一系列緩存,jdk spi 不支持緩存;

    2、dubbo 設計了默認初始化的類,jdk spi 不支持;

    3、dubbo 動態獲取 SPI 對象,jdk spi 需進行 for 循環判斷;

    4、dubbo 設計了 AOP 功能,XxxxFilterWrapper XxxxListenerWrapper;

    5、dubbo 設計了 IOC 功能,wrapperClass.getConstructor(type).newInstance(instance):

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章