1.dubbo源碼-dubbo嵌入spring

如果要弄明白dubbo如何嵌入spring中,首先要弄明白:spring.xml中的<dubbo>節點,spring是如何識別并解析的;

spring支持第三方命名空間

spring的擴展性非常強大,支持自定義第三方命令空間(不是<bean>的節點都是第三方命名空間,都要指定handler),具體實現方式為在META-INF/spring.handlers文件中以KV方式申明:第三方命名空間=處理類;例如添加對<aop>的支持(在spring-aop-3.2.16.RELEASE.jar包中META-INF/spring.handlers文件中有該定義,這里需要注意一點:http后的冒號":"前需要加轉移符"\"):
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler;

spring如何解析第三方命名空間

spring解析spring.xml的源碼在org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions()中,對應的源碼如下:

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    logger.debug("Loading bean definitions");
    Element root = doc.getDocumentElement();
    BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
    preProcessXml(root);
    parseBeanDefinitions(root, delegate);
    postProcessXml(root);
}

主要解析xml的業務邏輯在parseBeanDefinitions()中,如果namespaceUri為"http://www.springframework.org/schema/beans",那么isDefaultNamespace()為true,例如<bean>節點;如果解釋dubbo-demo-provider.xml中<dubbo:service>,那么由delegate.parseCustomElement(ele)處理。對應的源碼如下:

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if (delegate.isDefaultNamespace(root.getNamespaceURI())) {
        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;
                String namespaceUri = ele.getNamespaceURI();
                if (delegate.isDefaultNamespace(namespaceUri)) {
                    parseDefaultElement(ele, delegate);
                }
                else {
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        delegate.parseCustomElement(root);
    }
}

parseCustomElement(Element)的作用是根據namespaceUri得到NamespaceHandler,然后解釋當前xml,主要步驟如下:

  1. 加載所有類路徑下"META-INF/spring.handlers"文件中定義的handler集合得到Map;
  2. 根據namespaceUri得到其對應的NamespaceHandler,
  3. 用第2步得到的NamespaceHandler解析spring.xml中自定義的節點,例如<dubbo>,<aop>等;

spring解析xml中的<dubbo>

由于dubbo-config-spring模塊下的META-INF/spring.handlers文件中定義了
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
所以spring.xml中<dubbo>這樣的節點都由DubboNamespaceHandler進行解析;通過DubboNamespaceHandler源碼可知:<dubbo:service>會被DubboBeanDefinitionParser轉換成ServiceBean對象,如果xml中定義了<dubbo:application name="dubbo-test" owner="afei"/>,則會被DubboBeanDefinitionParser轉換成ApplicationConfig對象:

public class DubboNamespaceHandler extends NamespaceHandlerSupport {
    static {
        Version.checkDuplicate(DubboNamespaceHandler.class);
    }
    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 DubboBeanDefinitionParser(AnnotationBean.class, true));
    }
}

DubboBeanDefinitionParser.parse()中解析spring.xml中的<dubbo>節點,將相關屬性與其值封裝到RootBeanDefinition中;
RootBeanDefinition中的private volatile Object beanClass;就是具體對象,例如ApplicationConfig, RegistryConfig等;private MutablePropertyValues propertyValues;就是屬性&值的KV鍵值對;

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容