This debug code uses the dubo-demo-xml code in dubbo project dubbo on Github. The custom tags in the Spring XML file are resolved based on the classes specified in the Spring. handlers file, and the Dubbo tags are resolved in the Meta-INF/Spring. handlers file in the Dubbo-config-Spring JAR. Here’s the next consumer configuration file:

<beans 
       // XMLNS :xsi is the xSI tag namespace
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       // XMLNS :dubbo is the namespace of the dubbo tag
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       // The default namespace for the current XML file
       xmlns="http://www.springframework.org/schema/beans"
       // xsi:schemaLocation configures the configuration specification corresponding to each namespace and is used for format verification
       xsi:schemaLocation="Http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <! <dubbo:application name="demo-consumer"/ > <! --> <dubbo:registry address=Zookeeper: / / "127.0.0.1:2181" timeout="6000"/ > <! <dubbo:protocol name="dubbo"/ > <! -- Provider configuration --> <bean id="providerService" class="org.apache.dubbo.demo.provider.ProviderServiceImpl"/>
    <dubbo:service interface="org.apache.dubbo.demo.provider.ProviderServiceImpl" ref="providerService" timeout="60000"/ > <! <dubbo: Reference id="demoService" check="false" interface="org.apache.dubbo.demo.DemoService" timeout="6000" />

</beans>
Copy the code

XMLNS is specified namespace, here you can see configurations of dubbo namespace XMLNS: dubbo = “dubbo.apache.org/schema/dubb…

Get the parse class from the namespace of the Dubbo tag

Found by the namespace of the Dubbo tagMETA-INF/spring.handlersParse class in:

The matching process is shown as follows:

The init() method is responsible for registering the specific Parser class for each tag:

public void init(a) {
        this.registerBeanDefinitionParser("application".new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        this.registerBeanDefinitionParser("module".new DubboBeanDefinitionParser(ModuleConfig.class, true));
        this.registerBeanDefinitionParser("registry".new DubboBeanDefinitionParser(RegistryConfig.class, true));
        this.registerBeanDefinitionParser("config-center".new DubboBeanDefinitionParser(ConfigCenterBean.class, true));
        this.registerBeanDefinitionParser("metadata-report".new DubboBeanDefinitionParser(MetadataReportConfig.class, true));
        this.registerBeanDefinitionParser("monitor".new DubboBeanDefinitionParser(MonitorConfig.class, true));
        this.registerBeanDefinitionParser("metrics".new DubboBeanDefinitionParser(MetricsConfig.class, true));
        this.registerBeanDefinitionParser("ssl".new DubboBeanDefinitionParser(SslConfig.class, true));
        this.registerBeanDefinitionParser("provider".new DubboBeanDefinitionParser(ProviderConfig.class, true));
        this.registerBeanDefinitionParser("consumer".new DubboBeanDefinitionParser(ConsumerConfig.class, true));
        this.registerBeanDefinitionParser("protocol".new DubboBeanDefinitionParser(ProtocolConfig.class, true));
        // Configure the provider
        this.registerBeanDefinitionParser("service".new DubboBeanDefinitionParser(ServiceBean.class, true));
        // Consumer configuration
        this.registerBeanDefinitionParser("reference".new DubboBeanDefinitionParser(ReferenceBean.class, false));
        this.registerBeanDefinitionParser("annotation".new AnnotationBeanDefinitionParser());
    }
Copy the code

You can see that all sorts of parsing classes for dubbo tags are included, such as parsers for dubbo: Application, Dubbo: Registry, and Dubbo: Reference annotations in the configuration file above

2. Resolve the configuration into Beanfinition and register it with the BeanFactory procedure

Core logic in DubboBeanDefinitionParser parse method of a class, see DubboBeanDefinitionParser first class constructor:

public DubboBeanDefinitionParser(Class<? > beanClass,boolean required) {
        this.beanClass = beanClass;
        this.required = required;
    }
Copy the code

BeanClass is the type for each configuration, which is passed in by the init() method above, such as dubbo:reference, which corresponds to the ReferenceBean. The class parse method code is as follows.


  RootBeanDefinition beanDefinition = new RootBeanDefinition();
  // Set the type. When the Spring container instantiates a beanDefinition, it reflects the class's constructor to instantiate the bean objectbeanDefinition.setBeanClass(beanClass); .// Register the BeanDefinition in the container. This id will be stored as a beanName property in the BeanDefinition
  Void registerBeanDefinition(String beanName, BeanDefinition BeanDefinition); So id is passed in as beanName
			throws BeanDefinitionStoreException;
  if (StringUtils.isNotEmpty(id)) {
      parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
      beanDefinition.getPropertyValues().addPropertyValue("id", id); }...Dubbo: Reference configuration (id, interface, etc.) and place them in BeanDefinition
  NamedNodeMap attributes = element.getAttributes();
    len = attributes.getLength();

    for(i = 0; i < len; ++i) {
        Node node = attributes.item(i);
        name = node.getLocalName();
        if(! props.contains(name)) {if (parameters == null) {
                parameters = new ManagedMap();
            }

            String value = node.getNodeValue();
            parameters.put(name, newTypedStringValue(value, String.class)); }}if(parameters ! =null) {
        beanDefinition.getPropertyValues().addPropertyValue("parameters", parameters);
    }
     
Copy the code

There are three main steps:

  • Set of BeanDefinitionbeanClassProperties,beanClassBy the aboveinit()Method passed in, for example:dubbo:referenceThe correspondingReferenceBean.classWhen the Spring container instantiates a beanDefinition, it reflects the class’s constructor to instantiate the bean object
  • Get the BeanDefinitionRegistry for the bean using the parserContext of the parse method, and register the BeanDefinition with the BeanFactory. One key point is passed inidWill be asbeanNameSet it toBeanDefinitionFor dependency injection, the bean is found with the beanName key
  • Select the name of the configured property, such as id, interface, group, version, etc., and put these parameters into the propertyValueList of BeanDifinition (key = parameters). For later instantiation.

Now that the BeanDefinition has been parsed and registered in the container, the next step is for the Spring container to instantiate the BeanDefinition. How the provider and consumer sides are instantiated will be covered separately later.