Dubbo源碼分析之SPI(二)

1、概述

  本篇文章是dubbo SPI源碼分析的第二篇,接着第一篇繼續分析dubbo SPI的內容,咱們主要介紹 getDefaultExtension() 獲取默認擴展點方法。源碼分析

因爲此方法比較簡單,咱們略過示例部分,直接分析源碼。spa

2、源碼分析

  獲取默認擴展方法getDefaultExtension()是一個public、可對外提供調用的方法。咱們知道,dubbo中擴展點接口必需要有@SPI註解修飾,@SPI註解代碼以下:code

 1 @Documented
 2 @Retention(RetentionPolicy.RUNTIME)
 3 @Target({ElementType.TYPE})
 4 public @interface SPI {
 5 
 6     /**
 7      * default extension name
 8      */
 9     String value() default "";
10 
11 }

  註解能夠修飾類和接口,同時提供 一個默認爲空的value字段。對象

  這個value字段 就是本篇文章要介紹的默認擴展實現。blog

  如今咱們來看getDefaultExtension()方法內部:接口

1 public T getDefaultExtension() {
2     getExtensionClasses();
3     // cachedDefaultName爲@SPI中的value
4     if (null == cachedDefaultName || cachedDefaultName.length() == 0 || "true".equals(cachedDefaultName)) {
5         return null;
6     }
7     return getExtension(cachedDefaultName);
8 }

  第二行方法 getExtensionClasses()是加載配置文本文件,獲取配置的擴展點實現類,方法執行完,會把配置文本文件的key和擴展點實現類的Class對象存儲在cachedClasses 成員變量中,這個咱們在第一篇已經介紹過。字符串

  接下來就是方法的關鍵點,成員變量cachedDefaultName 的判斷了,若是cachedDefaultName 爲空或爲」true「 直接返回 null,若是cachedDefaultName 不爲空,則調用getExtension(..)方法,返回擴展點實現類對象。這個方法咱們在第一篇也已經介紹了。如今咱們只須要分析cachedDefaultName的賦值點 就ok 了。get

  成員變量cachedDefaultName 咱們在第一篇有介紹到,不知道你們是否還有印象,咱們如今看看變量定義:源碼

1 // SPI()內value,默認的接口實現
2 private String cachedDefaultName;

  私有的字符串變量。it

  變量cachedDefaultName的賦值,咱們先提早介紹下,其實就是在加載配置文本文件的過程當中進行的,具體的方法調用鏈爲:

1 getDefaultExtension() -->getExtensionClasses()-->loadExtensionClasses()

  這幾個方法咱們都有介紹,咱們如今看看loadExtensionClasses():

 1 private Map<String, Class<?>> loadExtensionClasses() {
 2     // 獲取註解 SPI的接口
 3     // type爲傳入的擴展接口,必須有@SPI註解
 4     final SPI defaultAnnotation = type.getAnnotation(SPI.class);
 5     // 獲取默認擴展實現value,若是存在,賦值給cachedDefaultName
 6     if (defaultAnnotation != null) {
 7         String value = defaultAnnotation.value();
 8         if ((value = value.trim()).length() > 0) {
 9             // @SPI value 只能是一個,不能爲逗號分割的多個
10             // @SPI value爲默認的擴展實現
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() + ": " + Arrays.toString(names));
14             }
15             if (names.length == 1)
16                 cachedDefaultName = names[0];
17         }
18     }
19     // 加載三個目錄配置的擴展類
20     Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
21     // META-INF/dubbo/internal
22     loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
23     // META-INF/dubbo
24     loadDirectory(extensionClasses, DUBBO_DIRECTORY);
25     // META-INF/services/
26     loadDirectory(extensionClasses, SERVICES_DIRECTORY);
27     return extensionClasses;
28 }

  沒錯,對cachedDefaultName的賦值,僅此一出。

  cachedDefaultName的內容就是解析@SPI註解的value內容。此處賦值後,getDefaultExtension()方法的返回就是根據這個值進行擴展點獲取並返回的。

3、總結

  獲取默認擴展點的方法getDefaultExtension() 邏輯很簡單,就是解析出註解@SPI的value內容,經過前一篇介紹的getExtension(..)方法進行擴展點獲取。若是@SPI沒有配置value或者設置的是」true「,getDefaultExtension()方法返回的就是null。

相關文章
相關標籤/搜索