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:
- objectFactory就是ExtensionFactory,他是通過ExtensionLoader.getExtensionLoader(ExtensionFactory.class)來實現的,但是他的值為null
- objectFactory的作用就是為dubbo的IOC提供所有物件
-------------------------getAdaptiveExtension() -------------------------
Adaptive
是一個註解,只能註解在類和方法上
- 註解在類上時:表示這個類時一個人工編碼,實現了一個裝飾類(裝飾者模式).例如:ExtensionFactory
- 註解在方法上:表示自動生成和編譯一個動態的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