中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Dubbo配置文件解析

發布時間:2020-06-24 15:30:11 來源:網絡 閱讀:658 作者:我叫袁蒙蒙 欄目:編程語言

1,配置信息

先看看dubbo官方文檔給出的初始化過程:

基于 dubbo.jar 內的 META-INF/spring.handlers 配置,Spring 在遇到 dubbo 名稱空間時,會回調 DubboNamespaceHandler。
所有 dubbo 的標簽,都統一用 DubboBeanDefinitionParser 進行解析,基于一對一屬性映射,將 XML 標簽解析為 Bean 對象。

找到dubbo.jar中的spring.handlers及DubboBeanDefinitionParser:

spring.handlers:

http\://dubbo.apache.org/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

DubboBeanDefinitionParser:

public class DubboNamespaceHandler extends NamespaceHandlerSupport {

    static {
        Version.checkDuplicate(DubboNamespaceHandler.class);
    }

    @Override
    public void init() {
        registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
        registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
    }
}

上述registerBeanDefinitionParser注冊對應標簽的解釋器,即當遇到"application"(即<dubbo:application/>)時,使用
new DubboBeanDefinitionParser(ApplicationConfig.class, true)對其進行解析。

dubbo配置文件及其意義:

 1、xmlns="http://www.springframework.org/schema/beans"  
聲明xml文件默認的命名空間,表示未使用其他命名空間的所有標簽的默認命名空間。  

2、xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
聲明XML Schema 實例,聲明后就可以使用 schemaLocation 屬性  

3、xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
聲明前綴為dubbo的命名空間,其惟一的作用是賦予命名空間一個惟一的名稱。當命名空間被定義在元素的開始標簽中時,所有帶有相同前綴的子元素都會與同一個命名空間相關聯。即當spring解析以dubbo開頭的標簽時,會把其命名空間設置為"http://code.alibabatech.com/schema/dubbo",而這個命名空間名稱和spring.handlers中的一個key是相同的,這即是它們產生聯系的地方。

4、xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"  
這個從命名可以看出個大概,指定Schema的位置這個屬性必須結合命名空間使用。這個屬性有兩個值,第一個
值表示需要使用的命名空間。第二個值表示供命名空間使用的 XML schema 的位置。  

2,源碼解析

配置文件解析發生在容器refresh的obtainFreshBeanFactory階段

調用棧:
Dubbo配置文件解析

進到XmlBeanDefinitionReader#doLoadBeanDefinitions中:

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {
        try {
            //將配置文件解析為Document對象,其中級聯包含子節點,每個子節點代表一個配置項
            Document doc = doLoadDocument(inputSource, resource);
            return registerBeanDefinitions(doc, resource);
        }
         ..........
    }

繼續往下走,來到DefaultBeanDefinitionDocumentReader#parseBeanDefinitions,這里開始遍歷解析子節點:

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if (delegate.isDefaultNamespace(root)) {
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                if (delegate.isDefaultNamespace(ele)) {
                    parseDefaultElement(ele, delegate);
                }
                else {
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        delegate.parseCustomElement(root);
    }
}

由于是自定義的配置,將會進入delegate.parseCustomElement(ele);

public BeanDefinition parseCustomElement(Element ele) {
    return parseCustomElement(ele, null);
}

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
    //獲取命名空間,如果是dubbo的配置,將會是"http://code.alibabatech.com/schema/dubbo"
    String namespaceUri = getNamespaceURI(ele);
    //更具命名空間,查找對應的Handler
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
        error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
        return null;
    }
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

進到DefaultNamespaceHandlerResolver#resolve:

public NamespaceHandler resolve(String namespaceUri) {
    //從jar包的META-INF/spring.handlers中讀取Handler信息
    Map<String, Object> handlerMappings = getHandlerMappings();
    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);
            if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
                throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
                        "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
            }
            //實例化Handler
            NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
            //執行初始化方法,指定不同的標簽各自使用的解析器
            namespaceHandler.init();
            handlerMappings.put(namespaceUri, namespaceHandler);
            return namespaceHandler;
        }
     .......
    }
}

進到getHandlerMappings方法:

private Map<String, Object> getHandlerMappings() {
    if (this.handlerMappings == null) {
        synchronized (this) {
            if (this.handlerMappings == null) {
                try {
                    Properties mappings =
                            PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
                    if (logger.isDebugEnabled()) {
                        logger.debug("Loaded NamespaceHandler mappings: " + mappings);
                    }
                    Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(mappings.size());
                    CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
                    this.handlerMappings = handlerMappings;
                }
            }
        }
    }
    return this.handlerMappings;
}

Dubbo配置文件解析

讀取文件的具體操作就不跟了,回到DefaultNamespaceHandlerResolver#resolve,看看獲取到的mapping:

Dubbo配置文件解析

其中一個則是以http://code.alibabatech.com/schema/dubbo 為鍵, DubboNamespaceHandler為值,因此,當解析dubbo的元素時,則會使用DubboNamespaceHandler

回到delegate.parseCustomElement,并進入到handler.parse中:

@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
    return findParserForElement(element, parserContext).parse(element, parserContext);
}

findParserForElement(element, parserContext),查找對應的解析器,即handler.init()中初始化的,然后對應解析器開始解析Element,最終在DubboBeanDefinitionParser#parse中進行構建RootBeanDefinition,并將構建好的RootBeanDefinition加入到容器中,并在容器refresh過程的finishBeanFactoryInitialization(beanFactory)中創建對應實例。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

富裕县| 盐池县| 平罗县| 开阳县| 萨嘎县| 太白县| 齐河县| 靖江市| 蓬莱市| 本溪市| 台山市| 澄迈县| 长垣县| 江孜县| 德兴市| 临泽县| 乌拉特中旗| 南皮县| 南京市| 长垣县| 许昌县| 会同县| 清远市| 威远县| 黔江区| 米易县| 宕昌县| 新营市| 榆中县| 手游| 伊宁市| 丁青县| 都江堰市| 泰宁县| 长葛市| 石城县| 沁源县| 大英县| 凤台县| 贞丰县| 克什克腾旗|