Dubbo原始碼解析之SPI

2021-08-30 13:33:44 字數 3954 閱讀 7961

dubbo版本:2.5.4

dubbo在服務發布過程中缺省會載入自適應的協議擴充套件,在類serviceconfig中存在以下初始化**,下面以此進行spi過程分析。

private

static

final protocol protocol = extensionloader.

getextensionloader

(protocol.

class).

getadaptiveextension()

;

相關註解

getextensionloader

該方法需要乙個class型別的引數,該引數表示希望載入的擴充套件點型別,該引數必須是介面,且該介面必須被@spi註解注釋,否則拒絕處理。檢查通過之後首先會檢查extensionloader快取中是否已經存在該擴充套件對應的extensionloader,如果有則直接返回,否則建立乙個新的extensionloader負責載入該擴充套件實現,同時將其快取起來。可以看到對於每乙個擴充套件,dubbo中只會有乙個對應的extensionloader例項

// extensionloader

public

static

extensionloader

getextensionloader

(class

type)if(

!withextensionannotation

(type)

)

extensionloader

loader =

(extensionloader

) extension_loaders.

get(type);if

(loader == null)

return loader;

}

getadaptiveextension

// extensionloader

public t getadaptiveextension()

catch

(throwable t)}}

}else

}return

(t) instance;

}

createadaptiveextension

// extensionloader

private t createadaptiveextension()

catch

(exception e)

}

getadaptiveextensionclass

// extensionloader

private class<

?>

getadaptiveextensionclass()

// 動態生成擴充套件點介面卡類》

return cachedadaptiveclass =

createadaptiveextensionclass()

;}

getextensionclasses

private map?>>

getextensionclasses()

}}return classes;

}

loadextensionclasses

private map?>>

loadextensionclasses()

if(names.length ==

1) cacheddefaultname = names[0]

;}}

map?>> extensionclasses =

newhashmap

?>>()

;// 載入meta-inf/dubbo、meta-inf/dubbo/internal、meta-inf/services 三個目錄下的擴充套件點實現類

loadfile

(extensionclasses, dubbo_internal_directory)

;loadfile

(extensionclasses, dubbo_directory)

;loadfile

(extensionclasses, services_directory)

;return extensionclasses;

}

loadfile:解析指定路徑下檔案獲取對應擴充套件點,通過反射機制例項化

private

void

loadfile

(map?>> extensionclasses, string dir)

else

if(urls != null)

if(line.

length()

>0)

/** * 判斷是否有自定義介面卡類

* adaptive註解加在類上,說明當前類就是自適應擴充套件點

* 加在方法上,則需要動態建立乙個自適應擴充套件點(protocol則對應protocol$adaptive)

*/if(clazz.

isannotationpresent

(adaptive.

class))

elseif(

! cachedadaptiveclass.

equals

(clazz))}

else

add(clazz);}

catch

(nosuchmethodexception e)

else}}

string[

] names = name_separator.

split

(name);if

(names != null && names.length >0)

for(string n : names)

class<

?> c = extensionclasses.

get(n);if

(c == null)

else

if(c != clazz)}}

}}}}

catch

(throwable t)}}

// end of while read lines

}finally

}catch

(throwable t)

}// end of while urls}}

catch

(throwable t)

}

回到getadaptiveextensionclass中的createadaptiveextensionclass方法

// extensionloader

private class<

?>

createadaptiveextensionclass()

回到createadaptiveextension中的injectextension擴充套件點注入方法

private t injectextension

(t instance)

}catch

(exception var9)}}

}}catch

(exception var10)

return instance;

}

至此,整個擴充套件點載入過程完成。

dubbo原始碼解析 spi 五

之前對dubbo的spi進行了四篇的分享.大家對這個概念有了一些初步的了解.談到程式設計水平如何高階,大家可能都會異口同聲的說出三個字,看原始碼.但是我卻始終認為,程式設計光看,是永遠學不會的.關鍵還是要多動手.但是很多時候,連怎麼看原始碼都無從下手,你叫我寫仿寫原始碼,這不是開玩笑?我們可以回憶一...

dubbo原始碼解析 spi 4

aop是老生常談的話題了,思想都不會是一蹴而就的.比如架構設計從all in one到soa也是乙個逐步演進的過程,所以本篇也講講這個aop的思想演進過程.假如我們就以aop最常用的場景事務來說,我們最初的做法是怎麼樣的?public class employeeserviceimpl implem...

Dubbo原始碼分析之SPI(二)

本篇文章是dubbo spi原始碼分析的第二篇,接著第一篇繼續分析dubbo spi的內容,我們主要介紹 getdefaultextension 獲取預設擴充套件點方法。由於此方法比較簡單,我們略過示例部分,直接分析原始碼。獲取預設擴充套件方法getdefaultextension 是乙個publi...