1. 程式人生 > >Dubbo原始碼-SPI(二)SPI的目的和實現

Dubbo原始碼-SPI(二)SPI的目的和實現

上篇,我們講了spi的目的和約定,那麼從這篇起,我們原始碼的角度來看dubbo spi到底做了什麼,怎麼實現的.

  • Dubbo spi的目的:

目的其實很假單,就是獲取一個實現類物件.

  • Dubbo spi的途徑:

ExtensionLoader.getExtension(String name)來獲取一個實現類物件.

  • Dubbo spi的實現路徑:
    • ExtensionLoader. getExtensionLoader(Class<T> type)
    • ExtensionLoader.public T getAdaptiveExtension() 
    • ExtensionLoader.getExtension(String name)
  • 原始碼閱讀,從第一行程式碼開始從main方法進入,初始化一個屬性,從這開始

------ExtensionLoader. getExtensionLoader(Class<T> type)--------

ExtensionLoader.getExtensionLoader(ExtensionFactory.class)

--->this.type=type;//初始化 type和objectFactory屬性,賦值之後儲存到快取中(map)

objectFactory=(type==ExtensionFactory.class?null:ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());

      --->ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());

            --->this.type=type

                  objectFactory=null

執行以上程式碼完成了2個屬性的初始化

1.每一個ExtensionLoader都包含2個值type和objectFactory.

                 Class<?>   type //構造器初始化時要得到的介面名

                 ExtensionFactory   objectFactory

2.建立一個ExtensionLoader 儲存在ConcurrentMap<Class<?>,ExtensionLoader<?>>EXTENSION_LOADERS中.

objectFactory:

  1. objectFactory就是ExtensionFactory,他是通過ExtensionLoader.getExtensionLoader(ExtensionFactory.class)來實現的,但是他的值為null
  2. objectFactory的作用就是為dubbo的IOC提供所有物件

-------------------------getAdaptiveExtension() -------------------------

Adaptive

是一個註解,只能註解在類和方法上

  1. 註解在類上時:表示這個類時一個人工編碼,實現了一個裝飾類(裝飾者模式).例如:ExtensionFactory
  2. 註解在方法上:表示自動生成和編譯一個動態的Adaptive類,例如Protocol$Adaptive

我們從Duboo的名稱空間為起始點,Protocol為例子來閱讀原始碼,瞭解getAdaptiveExtension()做了什麼事情

--->getAdaptiveExtension() //為cachedAdaptiveInstance(快取的adaptive例項)賦值

      --->createAdaptiveExtension()//獲取adaptive例項

             --->getAdaptiveExtensionClass()

                   --->getExtensionClasses()//為cachedClasses賦值.最後通過loadFile可知,如果類上上包含Adaptivre註解,那麼就是                                                                 人工編碼的類,直接獲取之後返回

                             --->loadExtensionClasses()

                                      --->loadFile//載入解析配置檔案(spi)中的內容,並存存放在快取變數中

                   -->createAdaptiveExtensionClass//如果不是人工編碼的(Adaptive註解在方法上),那麼就會動態建立編譯這個類.建立                                                                             的類是一個代理類

                   --->createAdaptiveExtensionClassCode()通過Adaptive模板來生成程式碼(生成結果如下)

                         

                   --->ExtensionLoader.getExtensionLoader(Compiler.class).getAdaptiveExtension();

                    --->compiler.compile(code,classLoader)//動態編譯類

            --->injectExtension()//進入IOC的控制反轉

loadFile()的目的與流程:

目的:載入解析配置檔案(某個類的spi)中的內容,並存存放在快取變數中,各種變數如下

cachedAdaptiveClass變數//如果這類上使用了Adaptivre註解,將其快取起來(註解在類上)

cachedWrapperClasses變數//如果類上沒使用Adaptivre註解,且其建構函式中包含介面(type)型別,如                                                                                            ProtocolFilterWrapper,ProtocolListenerWrapper才可以命中並快取

cachedActivates//剩下的如果類中包含Adaptivre註解,將其快取(註解在方法上)

cachedNames//其他的沒有被命中的放在這個變數中

至此spi在dubbo中的作用和實現就基本體現出來了,這次沒這麼配圖,抱歉.

匆忙之間寫出來了,以後會加上,希望各位同學還是自動動手debug下,可以加深下印象,

下一篇研究dubbo紫的的ioc和aop