2.2 dubbo-spi源碼解析

 1 package com.alibaba.dubbo.demo.test;
 2 
 3 import com.alibaba.dubbo.common.extension.ExtensionLoader;
 4 import com.alibaba.dubbo.rpc.Protocol;
 5 
 6 public class TestExtension {
 7     public static void main(String[] args) {
 8         ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
 9         final Protocol dubboProtocol = loader.getExtension("dubbo");
10         final Protocol adaptiveExtension = loader.getAdaptiveExtension();
11     }
12 }

講解這三行代碼的源碼。java

一  Protocol接口的定義spring

 1 package com.alibaba.dubbo.rpc;
 2 
 3 import com.alibaba.dubbo.common.URL;
 4 import com.alibaba.dubbo.common.extension.Adaptive;
 5 import com.alibaba.dubbo.common.extension.SPI;
 6 
 7 /**
 8  * Protocol. (API/SPI, Singleton, ThreadSafe)
 9  */
10 @SPI("dubbo")
11 public interface Protocol {
12 
13     /**
14      * 獲取缺省端口,當用戶沒有配置端口時使用。
15      *
16      * @return 缺省端口
17      */
18     int getDefaultPort();
19 
20     /**
21      * 暴露遠程服務:<br>
22      * 1. 協議在接收請求時,應記錄請求來源方地址信息:RpcContext.getContext().setRemoteAddress();<br>
23      * 2. export()必須是冪等的,也就是暴露同一個URL的Invoker兩次,和暴露一次沒有區別。<br>
24      * 3. export()傳入的Invoker由框架實現並傳入,協議不須要關心。<br>
25      *
26      * @param <T>     服務的類型
27      * @param invoker 服務的執行體
28      * @return exporter 暴露服務的引用,用於取消暴露
29      * @throws RpcException 當暴露服務出錯時拋出,好比端口已佔用
30      */
31     @Adaptive
32     <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
33 
34     /**
35      * 引用遠程服務:<br>
36      * 1. 當用戶調用refer()所返回的Invoker對象的invoke()方法時,協議需相應執行同URL遠端export()傳入的Invoker對象的invoke()方法。<br>
37      * 2. refer()返回的Invoker由協議實現,協議一般須要在此Invoker中發送遠程請求。<br>
38      * 3. 當url中有設置check=false時,鏈接失敗不能拋出異常,並內部自動恢復。<br>
39      *
40      * @param <T>  服務的類型
41      * @param type 服務的類型
42      * @param url  遠程服務的URL地址
43      * @return invoker 服務的本地代理
44      * @throws RpcException 當鏈接服務提供方失敗時拋出
45      */
46     @Adaptive
47     <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
48 
49     /**
50      * 釋放協議:<br>
51      * 1. 取消該協議全部已經暴露和引用的服務。<br>
52      * 2. 釋放協議所佔用的全部資源,好比鏈接和端口。<br>
53      * 3. 協議在釋放後,依然能暴露和引用新的服務。<br>
54      */
55     void destroy();
56 }

注意:這裏有兩個核心註解設計模式

  • @SPI:指定一個接口爲SPI接口(可擴展接口)
    1 @Documented
    2 @Retention(RetentionPolicy.RUNTIME)
    3 @Target({ElementType.TYPE})
    4 public @interface SPI {
    5     /** 缺省擴展點名 */
    6     String value() default "";
    7 }

     

  • @Adaptive該註解能夠註解在兩個地方:緩存

    • 接口上:例如AdaptiveExtensionFactory(該類不是工廠類,有特殊的邏輯)  AdaptiveCompiler(實際上也是工廠類,可是不能靠動態生成,不然會造成死循環)
    • 接口的方法上:會動態生成相應的動態類(其實是一個工廠類,工廠設計模式),例如Protocol$Adapter

這個接口極其重要,後續的整個服務暴露和服務調用會用到該接口的兩個方法。app

 

二 獲取ExtensionLoader框架

1 ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);

ExtensionLoader能夠類比爲JDK-SPI中的ServiceLoaderthis

首先來看一下ExtensionLoader的類屬性:url

 1     /** 存放SPI文件的三個目錄,其中META-INF/services/也是jdk的SPI文件的存放目錄 */
 2     private static final String SERVICES_DIRECTORY = "META-INF/services/";
 3     private static final String DUBBO_DIRECTORY = "META-INF/dubbo/";
 4     private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";//這個是最終jar包中存放spi文件的位置
 5 
 6     private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");
 7     /** key: SPI接口Class value: 該接口的ExtensionLoader */
 8     private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();
 9     /** key: SPI接口Class value: SPI實現類的對象實例 */
10     private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, Object>();

注意:上述的都是類屬性,即全部該類的實例都共享。然後邊的實例屬性就屬於每個類的實例私有spa

再來看一下ExtensionLoader的實例屬性:.net

 1     /** SPI接口Class */
 2     private final Class<?> type;
 3     /** SPI實現類對象實例的建立工廠 */
 4     private final ExtensionFactory objectFactory;
 5     /** key: ExtensionClass的Class value: SPI實現類的key */
 6     private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<Class<?>, String>();
 7     /** 存放全部的extensionClass */
 8     private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<Map<String, Class<?>>>();
 9 
10     private final Map<String, Activate> cachedActivates = new ConcurrentHashMap<String, Activate>();
11     /** 緩存建立好的extensionClass實例 */
12     private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<String, Holder<Object>>();
13     /** 緩存建立好的適配類實例 */
14     private final Holder<Object> cachedAdaptiveInstance = new Holder<Object>();
15     /** 存儲類上帶有@Adaptive註解的Class */
16     private volatile Class<?> cachedAdaptiveClass = null;
17     /** 默認的SPI文件中的key */
18     private String cachedDefaultName;
19     /** 存儲在建立適配類實例這個過程當中發生的錯誤 */
20     private volatile Throwable createAdaptiveInstanceError;
21     /** 存放具備一個type入參的構造器的實現類的Class對象 */
22     private Set<Class<?>> cachedWrapperClasses;
23     /** key :實現類的全類名  value: exception, 防止真正的異常被吞掉 */
24     private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<String, IllegalStateException>();

來看一下getExtensionLoader(Class<T> type)的源碼:

 1     /**
 2      * 1 校驗入參type:非空 + 接口 + 含有@SPI註解
 3      * 2 根據type接口從全局緩存EXTENSION_LOADERS中獲取ExtensionLoader,若是有直接返回;若是沒有,則先建立,以後放入緩存,最後返回
 4      */
 5     public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
 6         if (type == null)
 7             throw new IllegalArgumentException("Extension type == null");
 8         if (!type.isInterface()) {
 9             throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
10         }
11         if (!withExtensionAnnotation(type)) {
12             throw new IllegalArgumentException("Extension type(" + type +
13                     ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
14         }
15 
16         ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
17         if (loader == null) {
18             EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
19             loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
20         }
21         return loader;
22     }

建立ExtensionLoader:

1     private ExtensionLoader(Class<?> type) {
2         this.type = type;
3         objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
4     }

當前建立的ExtensionLoader對象(咱們取名爲ExtensionLoader對象1)的type是com.alibaba.dubbo.rpc.Protocol,因此此時會執行:ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()。

首先是建立ExtensionFactory,經過上邊核心類部分ExtensionFactory接口的源碼能夠看出,此類也是一個SPI接口類,且沒有指定默認的實現類的key。

1 ExtensionLoader.getExtensionLoader(ExtensionFactory.class)

下面的代碼與上述的過程類似,只是此時建立的另一個ExtensionLoader對象(咱們取名爲ExtensionLoader對象2)的type是com.alibaba.dubbo.common.extension.ExtensionFactory,而objectFactory是null。以後,這個ExtensionLoader對象2被放入EXTENSION_LOADERS緩存。這裏給出ExtensionFactory的定義,該類也極其重要。//TODO

1 package com.alibaba.dubbo.common.extension;
2 
3 @SPI
4 public interface ExtensionFactory {
5     <T> T getExtension(Class<T> type, String name);
6 }

以後執行ExtensionLoader對象2的getAdaptiveExtension()方法。

 1     /**
 2      * 首先從cachedAdaptiveInstance緩存中獲取AdaptiveExtension實例
 3      * 若是不爲null, 直接返回;
 4      * 若是爲null, 先建立AdaptiveExtension實例, 以後放入cachedAdaptiveInstance緩存中,最後返回
 5      */
 6     public T getAdaptiveExtension() {
 7         Object instance = cachedAdaptiveInstance.get();
 8         if (instance == null) {
 9             if (createAdaptiveInstanceError == null) {
10                 synchronized (cachedAdaptiveInstance) {
11                     instance = cachedAdaptiveInstance.get();
12                     if (instance == null) {
13                         try {
14                             instance = createAdaptiveExtension();
15                             cachedAdaptiveInstance.set(instance);
16                         } catch (Throwable t) {
17                             createAdaptiveInstanceError = t;
18                             throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);
19                         }
20                     }
21                 }
22             } else {
23                 throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
24             }
25         }
26 
27         return (T) instance;
28     }

來看createAdaptiveExtension()建立AdaptiveExtension的源碼:

 1     /**
 2      * createAdaptiveExtension()
 3      * --getAdaptiveExtensionClass()
 4      *   //從dubbo-spi配置文件中獲取AdaptiveExtensionClass
 5      *   --getExtensionClasses()
 6      *     --loadExtensionClasses()
 7      *       --loadFile(Map<String, Class<?>> extensionClasses, String dir)
 8      *   //建立動態代理類
 9      *   --createAdaptiveExtensionClass()
10      *
11      * --injectExtension(T instance)  //dubbo-ioc
12      */
13     private T createAdaptiveExtension() {
14         try {
15             return injectExtension((T) getAdaptiveExtensionClass().newInstance());
16         } catch (Exception e) {
17             throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(), e);
18         }
19     }

調用層級看註釋。injectExtension(T instance)方法只對objectFactory有用,若是objectFactory==null,則直接返回T instance。因此這裏返回的是getAdaptiveExtensionClass().newInstance()

來看getAdaptiveExtensionClass()的源碼:

 1     /**
 2      * 獲取ExtensionClasses和適配類
 3      * 若是實現類上帶有@Adaptive註解,直接建立修飾類
 4      * 若是方法上帶有@Adaptive註解,動態生成代理類
 5      */
 6     private Class<?> getAdaptiveExtensionClass() {
 7         getExtensionClasses();
 8         if (cachedAdaptiveClass != null) {
 9             return cachedAdaptiveClass;
10         }
11         return cachedAdaptiveClass = createAdaptiveExtensionClass();
12     }

如今來看getExtensionClasses():

 1     /**
 2      * 先從cachedClasses緩存中獲取全部的ExtensionClass,若是有,直接返回;
 3      * 若是沒有,經過loadExtensionClasses()從SPI文件中去讀取,以後寫入緩存
 4      */
 5     private Map<String, Class<?>> getExtensionClasses() {
 6         Map<String, Class<?>> classes = cachedClasses.get();
 7         if (classes == null) {
 8             synchronized (cachedClasses) {
 9                 classes = cachedClasses.get();
10                 if (classes == null) {
11                     classes = loadExtensionClasses();
12                     cachedClasses.set(classes);
13                 }
14             }
15         }
16         return classes;
17     }

如今來看loadExtensionClasses()

 1     /**
 2      * 1 從@SPI註解中將默認值解析出來,並緩存到cachedDefaultName中
 3      * 2 從SPI文件中獲取extensionClass並存儲到extensionClasses中,最後返回extensionClasses
 4      * 注意:此方法已經getExtensionClasses方法同步過。
 5      */
 6     private Map<String, Class<?>> loadExtensionClasses() {
 7         final SPI defaultAnnotation = type.getAnnotation(SPI.class);
 8         if (defaultAnnotation != null) {
 9             String value = defaultAnnotation.value();
10             if (value != null && (value = value.trim()).length() > 0) {
11                 String[] names = NAME_SEPARATOR.split(value);
12                 if (names.length > 1) {
13                     throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()
14                             + ": " + Arrays.toString(names));
15                 }
16                 if (names.length == 1) cachedDefaultName = names[0];
17             }
18         }
19 
20         Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
21         loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
22         loadFile(extensionClasses, DUBBO_DIRECTORY);
23         loadFile(extensionClasses, SERVICES_DIRECTORY);
24         return extensionClasses;
25     }

以後來看一下很是重要的一個方法loadFile(Map<String, Class<?>> extensionClasses, String dir)。

  1     /**
  2      * 1 加載dir目錄下的指定type名稱的文件(例如:dubbo-2.5.5.jar中的/META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory)
  3      * 2 遍歷該文件中的每一行
  4      * (1)獲取實現類key和value, 例如 name=spi, line=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
  5      * (2)根據line建立Class對象
  6      * (3)將具備@Adaptive註解的實現類的Class對象放在cachedAdaptiveClass緩存中, 注意該緩存只能存放一個具備@Adaptive註解的實現類的Class對象,若是有兩個知足條件,則拋異常
  7      * 下面的都是對不含@Adaptive註解的實現類的Class對象:
  8      * (4)查看是否具備含有一個type入參的構造器, 若是有(就是wrapper類), 將當前的Class對象放置到cachedWrapperClasses緩存中
  9      * (5)若是沒有含有一個type入參的構造器, 獲取無參構造器. 若是Class對象具備@Active註解, 將該對象以<實現類的key, active>存儲起來
 10      * (6)最後,將<Class對象, 實現類的key>存入cachedNames緩存,並將這些Class存入extensionClasses中.
 11      * @param extensionClasses
 12      * @param dir
 13      */
 14     private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
 15         String fileName = dir + type.getName();
 16         try {
 17             Enumeration<java.net.URL> urls;
 18             ClassLoader classLoader = findClassLoader();
 19             if (classLoader != null) {
 20                 urls = classLoader.getResources(fileName);
 21             } else {
 22                 urls = ClassLoader.getSystemResources(fileName);
 23             }
 24             if (urls != null) {
 25                 while (urls.hasMoreElements()) {
 26                     java.net.URL url = urls.nextElement();
 27                     try {
 28                         BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));
 29                         try {
 30                             String line = null;
 31                             while ((line = reader.readLine()) != null) {
 32                                 final int ci = line.indexOf('#');
 33                                 if (ci >= 0) line = line.substring(0, ci);
 34                                 line = line.trim();
 35                                 if (line.length() > 0) {
 36                                     try {
 37                                         String name = null;
 38                                         int i = line.indexOf('=');
 39                                         if (i > 0) {
 40                                             name = line.substring(0, i).trim();
 41                                             line = line.substring(i + 1).trim();
 42                                         }
 43                                         if (line.length() > 0) {
 44                                             Class<?> clazz = Class.forName(line, true, classLoader);
 45                                             if (!type.isAssignableFrom(clazz)) {
 46                                                 throw new IllegalStateException("Error when load extension class(interface: " +
 47                                                         type + ", class line: " + clazz.getName() + "), class "
 48                                                         + clazz.getName() + "is not subtype of interface.");
 49                                             }
 50                                             if (clazz.isAnnotationPresent(Adaptive.class)) {
 51                                                 if (cachedAdaptiveClass == null) {
 52                                                     cachedAdaptiveClass = clazz;
 53                                                 } else if (!cachedAdaptiveClass.equals(clazz)) {
 54                                                     throw new IllegalStateException("More than 1 adaptive class found: "
 55                                                             + cachedAdaptiveClass.getClass().getName()
 56                                                             + ", " + clazz.getClass().getName());
 57                                                 }
 58                                             } else {
 59                                                 try {
 60                                                     clazz.getConstructor(type);
 61                                                     Set<Class<?>> wrappers = cachedWrapperClasses;
 62                                                     if (wrappers == null) {
 63                                                         cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
 64                                                         wrappers = cachedWrapperClasses;
 65                                                     }
 66                                                     wrappers.add(clazz);
 67                                                 } catch (NoSuchMethodException e) {
 68                                                     clazz.getConstructor();
 69                                                     if (name == null || name.length() == 0) {
 70                                                         name = findAnnotationName(clazz);
 71                                                         if (name == null || name.length() == 0) {
 72                                                             if (clazz.getSimpleName().length() > type.getSimpleName().length()
 73                                                                     && clazz.getSimpleName().endsWith(type.getSimpleName())) {
 74                                                                 name = clazz.getSimpleName().substring(0, clazz.getSimpleName().length() - type.getSimpleName().length()).toLowerCase();
 75                                                             } else {
 76                                                                 throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + url);
 77                                                             }
 78                                                         }
 79                                                     }
 80                                                     String[] names = NAME_SEPARATOR.split(name);
 81                                                     if (names != null && names.length > 0) {
 82                                                         Activate activate = clazz.getAnnotation(Activate.class);
 83                                                         if (activate != null) {
 84                                                             cachedActivates.put(names[0], activate);
 85                                                         }
 86                                                         for (String n : names) {
 87                                                             if (!cachedNames.containsKey(clazz)) {
 88                                                                 cachedNames.put(clazz, n);
 89                                                             }
 90                                                             Class<?> c = extensionClasses.get(n);
 91                                                             if (c == null) {
 92                                                                 extensionClasses.put(n, clazz);
 93                                                             } else if (c != clazz) {
 94                                                                 throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + n + " on " + c.getName() + " and " + clazz.getName());
 95                                                             }
 96                                                         }
 97                                                     }
 98                                                 }
 99                                             }
100                                         }
101                                     } catch (Throwable t) {
102                                         IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t);
103                                         exceptions.put(line, e);
104                                     }
105                                 }
106                             } // end of while read lines
107                         } finally {
108                             reader.close();
109                         }
110                     } catch (Throwable t) {
111                         logger.error("Exception when load extension class(interface: " +
112                                 type + ", class file: " + url + ") in " + url, t);
113                     }
114                 } // end of while urls
115             }
116         } catch (Throwable t) {
117             logger.error("Exception when load extension class(interface: " +
118                     type + ", description file: " + fileName + ").", t);
119         }
120     }

上述的方法分別從三個目錄查找SPI文件並進行加載。在這裏只有在META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory中有值,內容以下:

1 adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
2 spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory 3 spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory

其中AdaptiveExtensionFactory在類上具備@Adaptive註解,這個類會在後續去講,這裏先略過。

執行事後,看一下:

  • cachedAdaptiveClass=class com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
  • extensionClasses=[{"spring","class com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory"}, {"spi", "class com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory"}],後續會這個集合存儲在cachedClasses緩存中。

上邊一直在講解getAdaptiveExtensionClass().newInstance()這句代碼中的getAdaptiveExtensionClass(),此方法返回一個com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory類,以後來看一下其newInstance()代碼,調用這個方法,默認會執行AdaptiveExtensionFactory的無參構造器。這裏給出AdaptiveExtensionFactory的完整代碼:

 1 package com.alibaba.dubbo.common.extension.factory;
 2 
 3 import com.alibaba.dubbo.common.extension.Adaptive;
 4 import com.alibaba.dubbo.common.extension.ExtensionFactory;
 5 import com.alibaba.dubbo.common.extension.ExtensionLoader;
 6 
 7 import java.util.ArrayList;
 8 import java.util.Collections;
 9 import java.util.List;
10 
11 /**
12  * AdaptiveExtensionFactory
13  */
14 @Adaptive
15 public class AdaptiveExtensionFactory implements ExtensionFactory {
16     private final List<ExtensionFactory> factories;
17 
18     /**
19      * 遍歷cachedClasses中緩存的extensionClasses的key,以後根據key來實例化對應的實現類,最後放置到EXTENSION_INSTANCES緩存中
20      */
21     public AdaptiveExtensionFactory() {
22         ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
23         List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
24         for (String name : loader.getSupportedExtensions()) {
25             list.add(loader.getExtension(name));
26         }
27         factories = Collections.unmodifiableList(list);
28     }
29 
30     public <T> T getExtension(Class<T> type, String name) {
31         for (ExtensionFactory factory : factories) {
32             T extension = factory.getExtension(type, name);
33             if (extension != null) {
34                 return extension;
35             }
36         }
37         return null;
38     }
39 }

從上能夠看出,這個裝飾類只是實例化好了各個ExtensionFactory(這裏是SpiExtensionFactory和SpringExtensionFactory),後續經過工廠獲取實現類實例都是由具體工廠來完成。

來看一下實例化代碼的地方,即loader.getExtension(name):

 1     /**
 2      * 從cachedInstances緩存中獲取name對應的實例,若是沒有,經過createExtension(name)建立,以後放入緩存
 3      * getExtension(String name)
 4      * --createExtension(String name)
 5      * ----injectExtension(T instance)
 6      */
 7     public T getExtension(String name) {
 8         if (name == null || name.length() == 0)
 9             throw new IllegalArgumentException("Extension name == null");
10         if ("true".equals(name)) {
11             return getDefaultExtension();
12         }
13         Holder<Object> holder = cachedInstances.get(name);
14         if (holder == null) {
15             cachedInstances.putIfAbsent(name, new Holder<Object>());
16             holder = cachedInstances.get(name);
17         }
18         Object instance = holder.get();
19         if (instance == null) {
20             synchronized (holder) {
21                 instance = holder.get();
22                 if (instance == null) {
23                     instance = createExtension(name);
24                     holder.set(instance);
25                 }
26             }
27         }
28         return (T) instance;
29     }

來看一下建立createExtension(name):

 1     private T createExtension(String name) {
 2         /** 從cachedClasses緩存中獲取全部的實現類map,以後經過name獲取到對應的實現類的Class對象 */
 3         Class<?> clazz = getExtensionClasses().get(name);
 4         if (clazz == null) {
 5             throw findException(name);
 6         }
 7         try {
 8             /** 從EXTENSION_INSTANCES緩存中獲取對應的實現類的Class對象,若是沒有,直接建立,以後放入緩存 */
 9             T instance = (T) EXTENSION_INSTANCES.get(clazz);
10             if (instance == null) {
11                 EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
12                 instance = (T) EXTENSION_INSTANCES.get(clazz);
13             }
14             injectExtension(instance);//ioc
15             Set<Class<?>> wrapperClasses = cachedWrapperClasses;
16             if (wrapperClasses != null && wrapperClasses.size() > 0) {
17                 for (Class<?> wrapperClass : wrapperClasses) {
18                     instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
19                 }
20             }
21             return instance;
22         } catch (Throwable t) {
23             throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
24                     type + ")  could not be instantiated: " + t.getMessage(), t);
25         }
26     }

這裏,就體現出來了dubbo-SPI比JDK-SPI的好處:dubbo-SPI不須要遍歷全部的實現類來獲取想要的實現類,能夠直接經過name來獲取。

injectExtension(instance)和wrapper包裝功能後續再說。

 

到此爲止,ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);這行代碼的整個源碼就講述完成了。最後來看一下整個代碼的執行結果。

類變量

  • ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS
    • "interface com.alibaba.dubbo.rpc.Protocol" -> "com.alibaba.dubbo.common.extension.ExtensionLoader[com.alibaba.dubbo.rpc.Protocol]"
    • "interface com.alibaba.dubbo.common.extension.ExtensionFactory" -> "com.alibaba.dubbo.common.extension.ExtensionLoader[com.alibaba.dubbo.common.extension.ExtensionFactory]"
  • ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES
    • "class com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory" -> SpringExtensionFactory實例
    • "class com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory" -> SpiExtensionFactory實例

ExtensionLoader<Protocol> loader的實例變量

  • Class<?> type = interface com.alibaba.dubbo.rpc.Protocol
  • ExtensionFactory objectFactory = AdaptiveExtensionFactory(適配類)
    • factories = [SpringExtensionFactory實例, SpiExtensionFactory實例]

總結:

第一點:ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(Class<T> type)最終獲得的實例變量是:

  • Class<?> type = interface T
  • ExtensionFactory objectFactory = AdaptiveExtensionFactory(適配類)
    • factories = [SpringExtensionFactory實例, SpiExtensionFactory實例]

第二點:ExtensionLoader<T>.getAdaptiveExtension()的調用層級

1 ExtensionLoader<T>.getAdaptiveExtension()
2 --createAdaptiveExtension()
3 ----injectExtension(getAdaptiveExtensionClass())
4 ------getAdaptiveExtensionClass()
5 --------getExtensionClasses()//從spi文件中查找實現類上具備@Adaptive註解的類
6 ----------loadExtensionClasses()
7 ------------loadFile(Map<String, Class<?>> extensionClasses, String dir)
8 --------createAdaptiveExtensionClass()//若是從spi文件中沒有找到實現類上具備@Adaptive註解的類,則動態建立類

最終返回的是建立好的Adaptive類,例如AdaptiveExtensionFactory實例。

第三點:ExtensionLoader<T>.getExtension()的調用層級

1 ExtensionLoader<T>.getExtension()
2 --createExtension(String name)
3 ----getExtensionClasses().get(name)//獲取擴展類
4 ----injectExtension(instance);//ioc
5 ----wrapper包裝;//aop

最終返回的是建立好的具體實現類,例如SpringExtensionFactory實例。 

 

至此,dubbo-spi源碼解析完成!!!

相關文章
相關標籤/搜索