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

Spring中的NamespaceHandler加載過程源碼詳解

 更新時間:2024年02月14日 08:13:06   作者:securitit  
這篇文章主要介紹了Spring中的NamespaceHandler加載過程源碼詳解,Spring提供的NamespaceHandler的處理機制,簡單來說就是命名空間處理器,Spring為了開放性提供了NamespaceHandler機制,這樣我們就可以根據(jù)需求自己來處理我們設(shè)置的標(biāo)簽元素,需要的朋友可以參考下

NamespaceHandler加載過程流程

在這里插入圖片描述

流程圖中羅列了Spring加載配置的整個過程,其中,從BeanDefinitionParserDelegate.parseCustomElement(...)開始,即開始了對命名空間NamespaceHandler的解析,本文對這部分內(nèi)容進行解析。

NamespaceHandler加載過程解析

1) BeanDefinitionParserDelegate.parseCustomElement(…)方法

① 取得指定元素的命名空間。

② 通過DefaultNamespaceHandlerResolver解析指定元素命名空間對應(yīng)的NamespaceHandler。

③ 通過查找的NamespaceHandler解析指定元素,取得Bean定義實例。

/**
 * 解析自定義元素.
 * @param ele 元素.
 * @param containingBd Bean定義.
 * @return 解析Bean定義.
 */
@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
    // 獲取元素命名空間.
    String namespaceUri = getNamespaceURI(ele);
    if (namespaceUri == null) {
        return null;
    }
    // 解析元素命名空間對應(yīng)的NamespaceHandler.
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
        error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
        return null;
    }
    // 解析當(dāng)前元素.
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

2) DefaultNamespaceHandlerResolver.resolve(…)方法

① 加載所有依賴的META-INF/spring.handlers文件,取得命名空間對應(yīng)處理器映射。

② 根據(jù)命名空間從①的映射中查找對應(yīng)的NamespaceHandler類。

③ 映射配置的NamespaceHandler類必須實現(xiàn)NamespaceHandler接口,否則拋出異常。

④ 根據(jù)配置映射的NamespaceHandler類路徑進行實例化。

⑤ 調(diào)用NamespaceHandler的init()方法,指定命名空間元素對應(yīng)的解析器。

/**
 * 從配置映射中查找所提供命名空間URI的NamespaceHandler.
 * @param namespaceUri 相關(guān)命名空間URI.
 * @return NamespaceHandler,若未找到,則為null.
 */
@Override
@Nullable
public NamespaceHandler resolve(String namespaceUri) {
    // 加載處理器映射.
    Map<String, Object> handlerMappings = getHandlerMappings();
    // 根據(jù)namespaceUri查找處理器類路徑.
    Object handlerOrClassName = handlerMappings.get(namespaceUri);
    if (handlerOrClassName == null) {
        return null;
    }
    else if (handlerOrClassName instanceof NamespaceHandler) {
        return (NamespaceHandler) handlerOrClassName;
    }
    else {
        String className = (String) handlerOrClassName;
        try {
            Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
            // 處理器需實現(xiàn)NamespaceHandler接口.
            if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
                throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
                                             "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
            }
            NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
            // NamespaceHandler初始化,指定命名空間下各元素對應(yīng)的解析器.
            namespaceHandler.init();
            handlerMappings.put(namespaceUri, namespaceHandler);
            return namespaceHandler;
        }
        catch (ClassNotFoundException ex) {
            throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
                                         "] for namespace [" + namespaceUri + "]", ex);
        }
        catch (LinkageError err) {
            throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
                                         className + "] for namespace [" + namespaceUri + "]", err);
        }
    }
}

3) DefaultNamespaceHandlerResolver.getHandlerMappings()方法

① 加載所有依賴的META-INF/spring.handlers文件,取得命名空間對應(yīng)處理器映射,存儲在Properties實例中。

② 將數(shù)據(jù)由Properties轉(zhuǎn)存到Map中。

/**
 * 延遲加載指定的NamespaceHandler映射.
 */
private Map<String, Object> getHandlerMappings() {
    Map<String, Object> handlerMappings = this.handlerMappings;
    if (handlerMappings == null) {
        synchronized (this) {
            handlerMappings = this.handlerMappings;
            if (handlerMappings == null) {
                try {
                    // 搜索META-INF/spring.handlers文件.
                    Properties mappings =
                        PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
                    if (logger.isDebugEnabled()) {
                        logger.debug("Loaded NamespaceHandler mappings: " + mappings);
                    }
                    Map<String, Object> mappingsToUse = new ConcurrentHashMap<>(mappings.size());
                    // 將Properties數(shù)據(jù)轉(zhuǎn)換到Map中.
                    CollectionUtils.mergePropertiesIntoMap(mappings, mappingsToUse);
                    handlerMappings = mappingsToUse;
                    this.handlerMappings = handlerMappings;
                }
                catch (IOException ex) {
                    throw new IllegalStateException(
                        "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
                }
            }
        }
    }
    return handlerMappings;
}

4) NamespaceHandlerSupport.parse(…)方法

① 使用提供元素的本地名稱查找BeanDefinitionParser。

② 調(diào)用BeanDefinitionParser實現(xiàn)進行解析。

/**
 * 通過委托給為Element注冊的BeanDefinitionParser來解析提供的Element.
 */
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
    // 使用提供元素的本地名稱查找BeanDefinitionParser.
    BeanDefinitionParser parser = findParserForElement(element, parserContext);
    // 調(diào)用BeanDefinitionParser實現(xiàn)進行解析.
    return (parser != null ? parser.parse(element, parserContext) : null);
}

5) NamespaceHandlerSupport.findParserForElement(…)方法

① 通過指定元素,取得元素的本地參數(shù)名稱。

② 根據(jù)本地名稱查找已注冊的BeanDefinitionParser。

/**
 * 使用提供的元素的本地名稱查找BeanDefinitionParser.
 */
@Nullable
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
    // 獲取提供元素的本地名稱.
    String localName = parserContext.getDelegate().getLocalName(element);
    // 根據(jù)本地名稱查找BeanDefinitionParser.
    BeanDefinitionParser parser = this.parsers.get(localName);
    if (parser == null) {
        parserContext.getReaderContext().fatal(
            "Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
    }
    return parser;
}

6) BeanDefinitionParser.parse(…)方法

BeanDefinitionParser.parse(...)是由具體開發(fā)進行編寫的,其中涉及元素解析、元素校驗、注冊對應(yīng)Beam。

總結(jié)

‘工欲善其事必先利其器’,只有當(dāng)對原理的了解達到一定程度,才能在實際遇到問題,簡潔、快速、高效的解決問題。

源碼解析基于spring-framework-5.0.5.RELEASE版本源碼。

若文中存在錯誤和不足,歡迎指正!

到此這篇關(guān)于Spring中的NamespaceHandler加載過程源碼詳解的文章就介紹到這了,更多相關(guān)NamespaceHandler加載過程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java連接池Druid獲取連接getConnection示例詳解

    java連接池Druid獲取連接getConnection示例詳解

    這篇文章主要為大家介紹了java連接池Druid獲取連接getConnection示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • java中ArrayList的兩種排序方法實例

    java中ArrayList的兩種排序方法實例

    ArrayList是一個數(shù)組隊列,相當(dāng)于 動態(tài)數(shù)組,與Java中的數(shù)組相比,它的容量能動態(tài)增長,這篇文章主要給大家介紹了關(guān)于java中ArrayList的兩種排序方法,需要的朋友可以參考下
    2021-07-07
  • SpringBoot中創(chuàng)建bean的7種方式總結(jié)

    SpringBoot中創(chuàng)建bean的7種方式總結(jié)

    Spring是一款廣泛應(yīng)用于企業(yè)級應(yīng)用程序開發(fā)的Java框架,其 IOC 和 DI 特性可以有效地管理應(yīng)用程序中的對象,提高了應(yīng)用程序的可維護性和可擴展性,那你知道spring有哪些方式將bean放入容器嘛,今天就給大家總結(jié)一下
    2023-07-07
  • Java8中的default方法詳解

    Java8中的default方法詳解

    這篇文章主要介紹了Java8中的default方法詳解,Java 8新增了default方法,它可以在接口添加新功能特性,而且還不影響接口的實現(xiàn)類,需要的朋友可以參考下
    2015-03-03
  • SpringMVC源碼之HandlerMapping處理器映射器解析

    SpringMVC源碼之HandlerMapping處理器映射器解析

    這篇文章主要介紹了SpringMVC源碼之HandlerMapping處理器映射器解析,在Spring?MVC中,HandlerMapping處理器映射器用于確定請求處理器對象,請求處理器可以是任何對象,只要它們使用了@Controller注解或注解@RequestMapping,需要的朋友可以參考下
    2023-08-08
  • Mybatis動態(tài)元素if的使用方式

    Mybatis動態(tài)元素if的使用方式

    這篇文章主要介紹了Mybatis動態(tài)元素if的使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Java之dao模式詳解及代碼示例

    Java之dao模式詳解及代碼示例

    這篇文章主要介紹了Java之dao模式詳解及代碼示例,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • springboot整合gateway實現(xiàn)網(wǎng)關(guān)功能的示例代碼

    springboot整合gateway實現(xiàn)網(wǎng)關(guān)功能的示例代碼

    本文主要介紹了springboot整合gateway實現(xiàn)網(wǎng)關(guān)功能的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 十五道tomcat面試題,為數(shù)不多的機會!

    十五道tomcat面試題,為數(shù)不多的機會!

    這篇文章主要介紹了十五道tomcat面試題,Tomcat的本質(zhì)是一個Servlet容器。一個Servlet能做的事情是:處理請求資源,并為客戶端填充response對象,需要的朋友可以參考下
    2021-08-08
  • Java中CaffeineCache自定義緩存時間的實現(xiàn)

    Java中CaffeineCache自定義緩存時間的實現(xiàn)

    本文主要介紹了Java中CaffeineCache自定義緩存時間的實現(xiàn),通過聲明緩存value值holder對象并創(chuàng)建緩存容器,可以為不同的key值指定不同的過期時間,具有一定的參考價值,感興趣的可以了解一下
    2025-02-02

最新評論

富锦市| 射洪县| 卢龙县| 永丰县| 和硕县| 濮阳市| 平顺县| 潮安县| 英吉沙县| 鄂州市| 高邑县| 即墨市| 保靖县| 香港| 洞口县| 韶山市| 虹口区| 鄂托克前旗| 伊春市| 抚州市| 静乐县| 宁南县| 志丹县| 西和县| 罗平县| 中卫市| 精河县| 崇仁县| 通州区| 桂东县| 综艺| 海原县| 牡丹江市| 曲周县| 利津县| 甘孜| 曲阜市| 海盐县| 汉沽区| 鄱阳县| 福贡县|