Dubbo實(shí)例注入過(guò)程
更新時(shí)間:2025年11月08日 10:32:16 作者:hello_zzw
文章主要介紹了Dubbo框架中ExtensionLoader類的創(chuàng)建、初始化、后處理和注入擴(kuò)展點(diǎn)的詳細(xì)過(guò)程,特別是通過(guò)AdaptiveExtensionInjector進(jìn)行注入的部分
Dubbo實(shí)例注入
org.apache.dubbo.common.extension.ExtensionLoader#createExtension
/**
* 根據(jù)指定擴(kuò)展點(diǎn)名稱去創(chuàng)建擴(kuò)展點(diǎn)實(shí)例對(duì)象
*/
@SuppressWarnings("unchecked")
private T createExtension(String name, boolean wrap) {
// getExtensionClasses 為當(dāng)前 SPI 接口的所有實(shí)現(xiàn)類的類信息集合
// 通過(guò)指定的擴(kuò)展點(diǎn)名稱 name 來(lái)獲取與之對(duì)應(yīng)的實(shí)現(xiàn)類類信息
Class<?> clazz = getExtensionClasses().get(name);
// 若找不到對(duì)應(yīng)的擴(kuò)展點(diǎn),或者當(dāng)初加載時(shí)擴(kuò)展點(diǎn)有重復(fù)名稱拋出異常
if (clazz == null || unacceptableExceptions.contains(name)) {
throw findException(name);
}
try {
// extensionInstances 為當(dāng)前 SPI 接口已經(jīng)經(jīng)過(guò)實(shí)例化的實(shí)例對(duì)象集合
// 然后通過(guò)指定的擴(kuò)展點(diǎn)名稱看看有沒有與之對(duì)應(yīng)的已經(jīng)曾經(jīng)創(chuàng)建好的實(shí)例對(duì)象
T instance = (T) extensionInstances.get(clazz);
// 若找不到,說(shuō)明沒有緩存,從而則說(shuō)明該擴(kuò)展點(diǎn)名稱也是首次使用
if (instance == null) {
// 通過(guò)并發(fā) Map 的 putIfAbsent 方法以線程安全的形式,
// 來(lái)保證該實(shí)現(xiàn)類只會(huì)創(chuàng)建一個(gè)實(shí)例對(duì)象,實(shí)例對(duì)象是反射方式創(chuàng)建出來(lái)的
extensionInstances.putIfAbsent(clazz, createExtensionInstance(clazz));
// 獲取剛剛創(chuàng)建的實(shí)例對(duì)象
instance = (T) extensionInstances.get(clazz);
// 初始化前置處理,即將原始的對(duì)象進(jìn)行前置包裝等處理
instance = postProcessBeforeInitialization(instance, name);
// 擴(kuò)展點(diǎn)注入
injectExtension(instance);
// 初始化后置處理,即將已初始化實(shí)例化注入的對(duì)象進(jìn)行后置包裝等處理
instance = postProcessAfterInitialization(instance, name);
}
// wrap 是否需要進(jìn)行裝飾器包裝
if (wrap) {
List<Class<?>> wrapperClassesList = new ArrayList<>();
// 看看是否有裝飾器包裝類,即實(shí)現(xiàn)類中單一參數(shù)的構(gòu)造方法是不是 SPI 接口
if (cachedWrapperClasses != null) {
wrapperClassesList.addAll(cachedWrapperClasses);
wrapperClassesList.sort(WrapperComparator.COMPARATOR);
Collections.reverse(wrapperClassesList);
}
if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
// 循環(huán)裝飾器包裝類,進(jìn)行層層套娃包裝
for (Class<?> wrapperClass : wrapperClassesList) {
// 裝飾器類上是否 Wrapper 注解
Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
// 1. 沒有 wrapper 注解,需要進(jìn)行包裝
// 2. wrapper 中的 matches 字段值為空沒有內(nèi)容,需要進(jìn)行包裝
// 3. wrapper 中的 matches 字段值不為空并包含入?yún)?name 值,并且 mismatches 字段值不包含 name 值,需要進(jìn)行包裝
// 4. 其他情況,可能就是瞎寫亂配,導(dǎo)致無(wú)法進(jìn)行包裝之類的
boolean match = (wrapper == null)
|| ((ArrayUtils.isEmpty(wrapper.matches())
|| ArrayUtils.contains(wrapper.matches(), name))
&& !ArrayUtils.contains(wrapper.mismatches(), name));
// 如果匹配成功,則進(jìn)行包裝
if (match) {
// 針對(duì)包裝的類再次進(jìn)行實(shí)例注入
instance = injectExtension(
(T) wrapperClass.getConstructor(type).newInstance(instance));
// 針對(duì)包裝類,同樣進(jìn)行后置處理
instance = postProcessAfterInitialization(instance, name);
}
}
}
}
// Warning: After an instance of Lifecycle is wrapped by cachedWrapperClasses, it may not still be Lifecycle
// instance, this application may not invoke the lifecycle.initialize hook.
initExtension(instance);
return instance;
} catch (Throwable t) {
throw new IllegalStateException(
"Extension instance (name: " + name + ", class: " + type + ") couldn't be instantiated: "
+ t.getMessage(),
t);
}
}
org.apache.dubbo.common.extension.ExtensionLoader#postProcessBeforeInitialization
/**
* 初始化前置處理方法
*/
@SuppressWarnings("unchecked")
private T postProcessBeforeInitialization(T instance, String name) throws Exception {
// 存在擴(kuò)展后處理器時(shí),循環(huán)處理所有的后置處理器
if (extensionPostProcessors != null) {
for (ExtensionPostProcessor processor : extensionPostProcessors) {
// 循環(huán)調(diào)用所有后置處理器中的初始化前置方法
instance = (T) processor.postProcessBeforeInitialization(instance, name);
}
}
// 返回處理后的對(duì)象
return instance;
}
/**
* 初始化后置處理方法
*/
@SuppressWarnings("unchecked")
private T postProcessAfterInitialization(T instance, String name) throws Exception {
// 如果實(shí)例實(shí)現(xiàn)了ExtensionAccessorAware,自動(dòng)注入extensionDirector作為擴(kuò)展訪問(wèn)器
if (instance instanceof ExtensionAccessorAware) {
((ExtensionAccessorAware) instance).setExtensionAccessor(extensionDirector);
}
// 存在擴(kuò)展后處理器時(shí),循環(huán)處理所有的后置處理器
if (extensionPostProcessors != null) {
for (ExtensionPostProcessor processor : extensionPostProcessors) {
// 循環(huán)調(diào)用所有后置處理器中的初始化后置方法
instance = (T) processor.postProcessAfterInitialization(instance, name);
}
}
return instance;
}
org.apache.dubbo.common.extension.ExtensionLoader#injectExtension
/**
* 注入擴(kuò)展點(diǎn)的方法
*/
private T injectExtension(T instance) {
if (injector == null) {
return instance;
}
try {
// 循環(huán)處理實(shí)例對(duì)象的所有public方法
for (Method method : instance.getClass().getMethods()) {
// 只處理set開頭,public修飾,只有一個(gè)參數(shù)的方法
if (!isSetter(method)) {
continue;
}
// 不處理帶有DisableInject注解的方法
if (method.isAnnotationPresent(DisableInject.class)) {
continue;
}
// 過(guò)濾掉實(shí)現(xiàn)自ScopeModelAware的方法
if (method.getDeclaringClass() == ScopeModelAware.class) {
continue;
}
// 過(guò)濾掉 ScopeModelAware、ExtensionAccessorAware 的方法
if (instance instanceof ScopeModelAware || instance instanceof ExtensionAccessorAware) {
if (ignoredInjectMethodsDesc.contains(ReflectUtils.getDesc(method))) {
continue;
}
}
// 獲取第一個(gè)參數(shù)
Class<?> pt = method.getParameterTypes()[0];
// 基礎(chǔ)類型不做處理
if (ReflectUtils.isPrimitives(pt)) {
continue;
}
try {
// 獲取set方法對(duì)應(yīng)的屬性
// set方法大于三個(gè)分字符時(shí),去除set后抽字母小寫
// 小于等于三個(gè)字符時(shí),返回""
String property = getSetterProperty(method);
// 根據(jù)參數(shù)類型、屬性名稱 從容器中獲取對(duì)應(yīng)的實(shí)例對(duì)象
Object object = injector.getInstance(pt, property);
if (object != null) {
// 獲取到實(shí)例對(duì)象時(shí),使用set方法設(shè)置到對(duì)象中
method.invoke(instance, object);
}
} catch (Exception e) {
logger.error(
COMMON_ERROR_LOAD_EXTENSION,
"",
"",
"Failed to inject via method " + method.getName() + " of interface " + type.getName() + ": "
+ e.getMessage(),
e);
}
}
} catch (Exception e) {
logger.error(COMMON_ERROR_LOAD_EXTENSION, "", "", e.getMessage(), e);
}
return instance;
}
org.apache.dubbo.common.extension.inject.AdaptiveExtensionInjector
@Override
public void initialize() throws IllegalStateException {
// 獲取【擴(kuò)展點(diǎn)注入器】的加載器
ExtensionLoader<ExtensionInjector> loader = extensionAccessor.getExtensionLoader(ExtensionInjector.class);
injectors = loader.getSupportedExtensions().stream()
// 從加載器中拿出所有的可被使用的注冊(cè)器實(shí)現(xiàn)類
.map(loader::getExtension)
// 包裝在不可變集合中
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
}
@Override
public <T> T getInstance(final Class<T> type, final String name) {
// 循環(huán)所有的擴(kuò)展點(diǎn)注入器
return injectors.stream()
// 從容器中根據(jù)類型加名字獲取實(shí)例對(duì)象
.map(injector -> injector.getInstance(type, name))
.filter(Objects::nonNull)
// 獲取到第一個(gè)就結(jié)束
.findFirst()
.orElse(null);
}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
JDBC連接mysql亂碼異常問(wèn)題處理總結(jié)
這篇文章主要介紹了JDBC連接mysql亂碼異常問(wèn)題處理的辦法和思路,有需要的朋友參考學(xué)習(xí)下。2017-12-12
多個(gè)springboot項(xiàng)目如何使用一個(gè)外部共同的application.yml
這篇文章主要介紹了多個(gè)springboot項(xiàng)目如何使用一個(gè)外部共同的application.yml問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
深入了解Java核心類庫(kù)--BigDecimal和System類
這篇文章主要為大家詳細(xì)介紹了javaBigDecimal和System類定義與使用的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能給你帶來(lái)幫助2021-07-07
解決Java?properties文件里面如何寫"\"的問(wèn)題
由于properties使用“\”相當(dāng)于是java的轉(zhuǎn)義符,如果想要寫出\的效果,只需修改相應(yīng)的寫法即可,對(duì)java?properties文件里的"\"寫法感興趣的朋友一起看看吧2022-04-04
java敏感詞過(guò)濾的實(shí)現(xiàn)方式
文章描述了如何搭建敏感詞過(guò)濾系統(tǒng)來(lái)防御用戶生成內(nèi)容中的違規(guī)、廣告或惡意言論,包括引入依賴、定義敏感詞類、非敏感詞類、替換詞類和工具類等步驟,并指出資源文件應(yīng)放在src/main/resources目錄下2025-12-12
Java通過(guò)SSH連接路由器輸入命令并讀取響應(yīng)的操作方法
最近需要讀取和修改華為路由器的配置,使用Java語(yǔ)言開發(fā),通過(guò)SSH連接,輸入命令并讀取響應(yīng),接下來(lái)通過(guò)本文給大家介紹下Java通過(guò)SSH連接路由器,輸入命令并讀取響應(yīng),需要的朋友可以參考下2024-01-01
基于visualvm監(jiān)控類實(shí)現(xiàn)過(guò)程詳解
這篇文章主要介紹了基于visualvm監(jiān)控類實(shí)現(xiàn)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09

