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...