1.dubbo源码-dubbo嵌入spring

如果要弄明白dubbo如何嵌入spring中,首先要弄明白:spring.xml中的节点,spring是如何识别并解析的;

spring支持第三方命名空间

spring的扩展性非常强大,支持自定义第三方命令空间(不是的节点都是第三方命名空间,都要指定handler),具体实现方式为在META-INF/spring.handlers文件中以KV方式申明:第三方命名空间=处理类;例如添加对的支持(在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,例如节点;如果解释dubbo-demo-provider.xml中,那么由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中自定义的节点,例如等;

spring解析xml中的

由于dubbo-config-spring模块下的META-INF/spring.handlers文件中定义了
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
所以spring.xml中这样的节点都由DubboNamespaceHandler进行解析;通过DubboNamespaceHandler源码可知:会被DubboBeanDefinitionParser转换成ServiceBean对象,如果xml中定义了,则会被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中的节点,将相关属性与其值封装到RootBeanDefinition中;
RootBeanDefinition中的private volatile Object beanClass;就是具体对象,例如ApplicationConfig, RegistryConfig等;private MutablePropertyValues propertyValues;就是属性&值的KV键值对;

你可能感兴趣的:(1.dubbo源码-dubbo嵌入spring)