Dubbo Principle and Label Resolution of Source Code Resolution

Posted by tefflox on Wed, 15 May 2019 09:31:45 +0200

I. Dubbo Configuration

Dubbo supports multiple configurations:

  • XML Configuration: Implementation of Spring-based Schema and XML Extension Mechanism
  • Property Configuration: Load dubbo.properties under the classpath root directory
  • API configuration: Hardcoded configuration (not recommended)
  • Annotation Configuration: Configuration by Annotation (Dubbo-2.5.7 and above version support, not recommended)

For attribute configuration, dubbo.properties files can be specified by environment variables and - D startup parameters in the order of loading files:

    1. - D startup parameter
    2. environment variable
    3. classpath root directory

The loading code is as follows:

public static final String DUBBO_PROPERTIES_KEY = "dubbo.properties.file";
public static final String DEFAULT_DUBBO_PROPERTIES = "dubbo.properties";

private static volatile Properties PROPERTIES;

public static Properties getProperties() {
    if (PROPERTIES == null) {
        synchronized (ConfigUtils.class) {
            if (PROPERTIES == null) {
                String path = System.getProperty(Constants.DUBBO_PROPERTIES_KEY);
                if (path == null || path.length() == 0) {
                    path = System.getenv(Constants.DUBBO_PROPERTIES_KEY);
                    if (path == null || path.length() == 0) {
                        path = Constants.DEFAULT_DUBBO_PROPERTIES;
                    }
                }
                PROPERTIES = ConfigUtils.loadProperties(path, false, true);
            }
        }
    }
    return PROPERTIES;
}

This paper mainly analyses the implementation principle and source code of XML configuration, other ways are not to be described in detail.

II. XML Configuration

As mentioned at the beginning of the article, XML configuration is based on Spring's Schema and XML extension mechanism. Through this mechanism, we can write our own Schema and configure beans according to the custom Schema tags.

There are several steps to use Spring's XML extension mechanism:

    1. Define Schema (write. xsd file)
    2. Define JavaBean
    3. Write Namespace Handler and Bean Definition Parser to complete Schema parsing
    4. Write spring.handlers and spring.schemas file series parsing components
    5. Application Configuration in XML Files
Dubbo configures the relevant code in the dubbo-config module.

2.1 Definition of Schema

The definition of Schema is embodied in the. xsd file, which is located under the dubbo-config-spring sub-module:

As for XSD's data type and how to define it, it is not the focus of this article. Please refer to W3school.< Schema tutorial>.

2.2 Define JavaBean

In the dubbo-config-api sub-module, the JavaBeans corresponding to all Dubbo tags are defined, and the attributes in JavaBeans correspond to the configuration items of the tags one by one.

2.3 Analytic Schema

The Schema analysis of the Dubbo service framework is implemented through Dubbo Namespace Handler and Dubbo Bean Definition Parser.

Among them, Dubbo Namespace Handler extends Spring's Namespace Handler Support by rewriting its init() method to register the corresponding parsers for each tag:

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));
    }
}

DubboBean Definition Parser implements Spring's Bean Definition Parser, which resolves tags to corresponding JavaBean s by rewriting parse():

public class DubboBeanDefinitionParser implements BeanDefinitionParser {
    public BeanDefinition parse(Element element, ParserContext parserContext) {
    return parse(element, parserContext, beanClass, required);
    }

    @SuppressWarnings("unchecked")
    private static BeanDefinition parse(Element element,ParserContext parserContext,Class<?> beanClass,boolean required) {
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClass(beanClass);
        beanDefinition.setLazyInit(false);
        //......ellipsis
        if (ProtocolConfig.class.equals(beanClass)) {
            for (String name : parserContext.getRegistry().getBeanDefinitionNames()) {
                BeanDefinition definition = parserContext.getRegistry().getBeanDefinition(name);
                PropertyValue property = definition.getPropertyValues().getPropertyValue("protocol");
                if (property != null) {
                    Object value = property.getValue();
                    if (value instanceof ProtocolConfig && id.equals(((ProtocolConfig) value).getName())) {
                        definition.getPropertyValues().addPropertyValue("protocol", new RuntimeBeanReference(id));
                    }
                }
            }
        } else if (ServiceBean.class.equals(beanClass)) {
            String className = element.getAttribute("class");
            if(className != null && className.length() > 0) {
                RootBeanDefinition classDefinition = new RootBeanDefinition();
                classDefinition.setBeanClass(ReflectUtils.forName(className));
                classDefinition.setLazyInit(false);
                parseProperties(element.getChildNodes(), classDefinition);
                beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));
            }
        } else if (ProviderConfig.class.equals(beanClass)) {
            parseNested(element, parserContext, ServiceBean.class, true, "service", "provider", id, beanDefinition);
        } else if (ConsumerConfig.class.equals(beanClass)) {
            parseNested(element, parserContext, ReferenceBean.class, false, "reference", "consumer", id, beanDefinition);
        }
        //......ellipsis
        return beanDefinition;
    }
}

2.4 Series Components

We already know the implementation class of parsing, so how does Spring know to parse Dubbo tags with Dubbo Namespace Handler? This is achieved by writing the spring.handlers file.

Spr.handlers are as follows:

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

Spring then learns from the spring.schemas file that the Schema of the Dubbo tag is dubbo.xsd, and checks the format of the applied XML configuration file.

The spring.schemas file is as follows:

http\://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd

The location of the document is as follows:

2.5 Application Configuration

Through the above steps, the Dubbo service framework completes the function of tag parsing. Users can configure XML in the application according to the format of dubbo.xsd.

Over.

Topics: Java Dubbo Spring xml Attribute