About the introduction of Dubbo and use, and the design of the framework, website dubbo.apache.org/zh/docs/v2…. (version 2.7) are introduced. I believe that as long as you are patient, you can basically have an overall understanding of Dubbo. It is important to note that you need to have at least a basic understanding of Dubbo so that you don’t get confused about the source code.

The official documentation for Dubbo is pretty good. In addition to the user manual, there is an introduction to the principles and even an analysis of the source code. But I think there are still shortcomings, that is, the analysis of the official website soon into the details, after reading the brain is still buzzing, I think the lack of a grasp of the overall, as well as between modules or interfaces between interfaces.

Next, we understand the integration of Spring and Dubbo. Just as the last few articles have analyzed the principle of Spring IoC, so follow the lead and analyze the application of Spring IoC extension, which is the integration of Dubbo.

As of this writing, Dubbo has been updated to 3.0.1, and my analysis is based on the 2.6.x branch.

Dubbo module partition, do still quite good of, reference dubbo.apache.org/zh/docs/v2…. , seen from the module, and Spring integration module is dubbo – config – Spring, there are two key categories, one is com. Alibaba. Dubbo. Config. Spring. ServiceBean, One is com. Alibaba. Dubbo. Config. Spring. ReferenceBean, as can be seen from the name, ServiceBean is related to service export and registration, ReferenceBean is associated with a service reference, basically see ServiceBean here.

ServiceBean class

Take a look at the inheritance architecture of ServiceBean

Interesting ~, the graph generating ServiceBean ApplicationContextAware, so can inject ApplicationContext, realize ApplicationEventPublisherAware, so you can publish event, It is also an ApplicationListener, so it can receive events, and DisposableBean and InitializingBean, so that you can perform some extended functions when the Bean is initialized and destroyed.

The first is the afterPropertiesSet() method

public void afterPropertiesSet(a) throws Exception {
	
	/ /... Omit, related to loading configuration, but not this time
	
	if (!isDelay()) {
		export();
	}
}
Copy the code

If the service is not delayed exposed, it will be exposed in afterPropertiesSet, but when I run the single test locally, delay is empty, so isDelay() returns true. There is no service exposed here, so look at onApplicationEvent(), which is triggered when the container event is refreshed

public void onApplicationEvent(ContextRefreshedEvent event) {
	if(isDelay() && ! isExported() && ! isUnexported()) {if (logger.isInfoEnabled()) {
			logger.info("The service ready on spring started. service: "+ getInterface()); } export(); }}Copy the code

This method is simpler and calls export() to the same method as above, so extension integration is also easier

There is also the question of how, for example, Dubbo’s beans are managed by the Spring IoC container

DubboNamespaceHandler class

So here’s an example,

Add the Spring. handlers file to the meta-INF directory in the classpath

http\://bubbo.apache.org/schema/bubbo=spring.schema.BubboNamespaceHandler
Copy the code

In addition, add the spring.schemas file, whose content is

http\://bubbo.apache.org/schema/bubbo/bubbo.xsd=META-INF/bubbo.xsd
Copy the code

Finally, add bubbo. XSD. If you don’t know XML schema, you can go to see it first

<? xml version="1.0" encoding="UTF-8" standalone="no"? > <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:beans="http://www.springframework.org/schema/beans"
            xmlns:tool="http://www.springframework.org/schema/tool"
            xmlns="http://bubbo.apache.org/schema/bubbo"
            targetNamespace="http://bubbo.apache.org/schema/bubbo">

    <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
    <xsd:import namespace="http://www.springframework.org/schema/beans"/>
    <xsd:import namespace="http://www.springframework.org/schema/tool"/>

    <xsd:element name="bubbo">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:attribute name="protocol" type="xsd:string" />
                    <xsd:attribute name="version" type="xsd:string" />
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

</xsd:schema>
Copy the code

<bubbo:protocol=”bubbo” version=”1.0.0″/>

The key is to parse these schemas, such as the BubboNamespaceHandler

public class BubboNamespaceHandler extends NamespaceHandlerSupport {

    @Override
    public void init(a) {
        System.out.println("BubboNamespaceHandler..."); }}Copy the code

And DubboNamespaceHandler configuration parsing, all by DubboBeanDefinitionParser, this class implements the BeanDefinitionParser

public class DubboNamespaceHandler extends NamespaceHandlerSupport {

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

    @Override
    public void init(a) {
        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".newAnnotationBeanDefinitionParser()); }}Copy the code

Maybe we want to ask again, when does this parse get triggered

The key is

DefaultBeanDefinitionDocumentReader

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;
				// This determines whether to load Spring's namespace or a custom namespace
				if (delegate.isDefaultNamespace(ele)) {
					parseDefaultElement(ele, delegate);
				}
				else{ delegate.parseCustomElement(ele); }}}}else{ delegate.parseCustomElement(root); }}Copy the code

So, the idea of integration is simple