最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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)名稱看看有沒(méi)有與之對(duì)應(yīng)的已經(jīng)曾經(jīng)創(chuàng)建好的實(shí)例對(duì)象
        T instance = (T) extensionInstances.get(clazz);
        // 若找不到,說(shuō)明沒(méi)有緩存,從而則說(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. 沒(méi)有 wrapper 注解,需要進(jìn)行包裝
                    // 2. wrapper 中的 matches 字段值為空沒(méi)有內(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開(kāi)頭,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)題處理總結(jié)

    這篇文章主要介紹了JDBC連接mysql亂碼異常問(wèn)題處理的辦法和思路,有需要的朋友參考學(xué)習(xí)下。
    2017-12-12
  • 多個(gè)springboot項(xiàng)目如何使用一個(gè)外部共同的application.yml

    多個(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類

    深入了解Java核心類庫(kù)--BigDecimal和System類

    這篇文章主要為大家詳細(xì)介紹了javaBigDecimal和System類定義與使用的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能給你帶來(lái)幫助
    2021-07-07
  • 解決Java?properties文件里面如何寫"\"的問(wèn)題

    解決Java?properties文件里面如何寫"\"的問(wèn)題

    由于properties使用“\”相當(dāng)于是java的轉(zhuǎn)義符,如果想要寫出\的效果,只需修改相應(yīng)的寫法即可,對(duì)java?properties文件里的"\"寫法感興趣的朋友一起看看吧
    2022-04-04
  • Java操作Excel的示例詳解

    Java操作Excel的示例詳解

    在平時(shí)可以使用IO流對(duì)Excle進(jìn)行操作,但是現(xiàn)在使用更加方便的第三方組件來(lái)實(shí)現(xiàn)。本文就來(lái)和大家聊聊Java如何通過(guò)第三方組件實(shí)現(xiàn)操作Excel,需要的可以參考一下
    2023-01-01
  • java敏感詞過(guò)濾的實(shí)現(xiàn)方式

    java敏感詞過(guò)濾的實(shí)現(xiàn)方式

    文章描述了如何搭建敏感詞過(guò)濾系統(tǒng)來(lái)防御用戶生成內(nèi)容中的違規(guī)、廣告或惡意言論,包括引入依賴、定義敏感詞類、非敏感詞類、替換詞類和工具類等步驟,并指出資源文件應(yīng)放在src/main/resources目錄下
    2025-12-12
  • Java 讀取指定路徑的文本文件并返回String的方法

    Java 讀取指定路徑的文本文件并返回String的方法

    今天小編就為大家分享一篇Java 讀取指定路徑的文本文件并返回String的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • 熟悉maven:使java開(kāi)發(fā)變得更高效

    熟悉maven:使java開(kāi)發(fā)變得更高效

    在日常的開(kāi)發(fā)過(guò)程中,maven是很常見(jiàn)的項(xiàng)目構(gòu)建工具。maven可以極大的提高我們的開(kāi)發(fā)效率,幫助我們簡(jiǎn)化開(kāi)發(fā)過(guò)程中一些解決依賴和項(xiàng)目部署的相關(guān)問(wèn)題,所以學(xué)習(xí)掌握maven的相關(guān)知識(shí)是非常有必要的
    2021-06-06
  • Java通過(guò)SSH連接路由器輸入命令并讀取響應(yīng)的操作方法

    Java通過(guò)SSH連接路由器輸入命令并讀取響應(yīng)的操作方法

    最近需要讀取和修改華為路由器的配置,使用Java語(yǔ)言開(kāi)發(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ò)程詳解

    這篇文章主要介紹了基于visualvm監(jiān)控類實(shí)現(xiàn)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09

最新評(píng)論

清水河县| 拉萨市| 获嘉县| 伊通| 元朗区| 建昌县| 沧源| 射洪县| 茶陵县| 九台市| 阿尔山市| 井研县| 大冶市| 隆德县| 志丹县| 大名县| 镇平县| 阿拉尔市| 吴堡县| 濮阳县| 武胜县| 安岳县| 延长县| 常熟市| 葫芦岛市| 正安县| 衡山县| 淳化县| 平塘县| 大邑县| 贺州市| 呼玛县| 安平县| 长宁县| 楚雄市| 来凤县| 图木舒克市| 信宜市| 米泉市| 大港区| 潜江市|