Origin Dubbo, talk about Spring XML Schema extension mechanism

background

In Dubbo, you can use the XML configuration-related information, can also be used to introduce the service or export service. Configuration is complete, start the project, Spring reads the configuration file, generate injected related Bean. Then how to implement a custom Dubbo Spring loaded XML is read?

Spring XML Schema extension mechanism. Starting Spring 2.0, Spring begins there is provided a XML-based extension mechanism Schema, to define and configure bean.

Spring XML Schema extension mechanism

Spring XML Schema extensions to achieve, is actually very simple, only we need to complete the following four steps.

  1. Creating XML Schema file, because the file suffix xsd, referred to below as XSD file.
  2. Writing implements one or more BeanDefinitionParser.
  3. Write NamespaceHandlerimplementation class.
  4. Sign up NamespaceHandlerand XSD files.

We follow the above steps, the final full Spring resolved as follows.

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:demo="http://www.test.com/demo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.test.com/demo http://www.test.com/demo/demo.xsd">

    <demo:application name="test" id="test"/>
</beans>

Creating XSD file

XSD file, mainly used to define the XML format, used to verify the legitimacy of XML. In the IDE, import the XSD files, editing XML files can get tips.

Here we generate a XSD file.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.test.com/demo"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:beans="http://www.springframework.org/schema/beans"
            targetNamespace="http://www.test.com/demo"
            elementFormDefault="qualified"
            attributeFormDefault="unqualified">

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

    <xsd:element name="application">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:attribute name="name" type="xsd:string" use="required"/>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

</xsd:schema>

The above XSD file http://www.test.com/demo custom namespace address below will be used to.

Achieve BeanDefinitionParser

Here achieve BeanDefinitionParser , XML parsing real action done here.

As the above example is relatively simple, we can inherit the abstract class Spring provides direct AbstractSingleBeanDefinitionParserand related methods to achieve it.

public class DemoBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    /**

     * 返回最会需要注入 Spring Bean 的类型
     * @param element
     * @return
     */
    @Override
    protected Class<?> getBeanClass(Element element) {
        return DemoApplication.class;
    }

    /***
     * 这个方法完成真正解析动作
     * @param element
     * @param builder
     */
    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        String name=element.getAttribute("name");
        builder.addPropertyValue("name",name);
    }
}

Of course, you can directly implement BeanDefinitionParser , this is more flexible, but this compared to the above this is more complicated.

public class BeanApplicationDefinitionParser implements BeanDefinitionParser {

    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {

        String name=element.getAttribute("name");
        // Bean 定义,最后根据这个生产 Bean
        RootBeanDefinition rootBeanDefinition=new RootBeanDefinition();
        rootBeanDefinition.setBeanClass(DemoApplication.class);
        rootBeanDefinition.setLazyInit(false);
        // 添加解析的属性
        rootBeanDefinition.getPropertyValues().add("name",name);
        // 将生成的 BeanDefinition 注册,少了这一步将会导致最后生成 Bean 时报错
        parserContext.getRegistry().registerBeanDefinition("application",rootBeanDefinition);
        return rootBeanDefinition;
    }
}

Achieve NamespaceHandler

This step is achieved NamespaceHandler, as long as the developers to customize NamespaceHandler inherit NamespaceHandlerSupportthe abstract class, implement initmethods. In this method step towards registering above BeanDefinitionParser.

public class DemoNameSpaceHandler extends NamespaceHandlerSupport {

    @Override

    public void init() {

        // elementName 为命名空间
        registerBeanDefinitionParser("application",new BeanApplicationDefinitionParser());
    }
}

Sign up and XSD NamespaceHandler

This step we need to generate two configuration files in META-INF, respectively spring.handlers, spring.schemas.

spring.schemas Specify the XSD file path.

http\://www.test.com/demo/demo.xsd=com/spring/learning/xml/schemas/autoring/leanrn/demo.xsd

spring.handlersSpecifies the NamespaceHandlerfull class name, contains both the front of the package name.

It should be noted that need to be escaped

Test Run

First, we produce Spring XML configuration file.

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:demo="http://www.test.com/demo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.test.com/demo http://www.test.com/demo/demo.xsd">

    <demo:application name="test" id="test"/>
</beans>

It should be noted the need to use XSD file definitions http://www.test.com/demo.

Then we use SpringBoot, import the XML file, then run.

@SpringBootApplication
@ImportResource(locations = {"classpath:applicationContext.xml"})
public class XmlSchemaApplication {


    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(XmlSchemaApplication.class, args);
        DemoApplication demoApplication=applicationContext.getBean(DemoApplication.class);
        System.out.println("application name is "+demoApplication.getName());
    }
}

The output is:

output
application name is test

Spring XML extension mechanism Source Research

Here we focus on how to customize the XML file extension is Spring loaded.

Spring will start the process by BeanDefinitionDocumentReaderreading the label inside the beans all configurations, through this process will BeanDefinitionParserDelegate#parseCustomElementresolve the custom elements.

carbon34.png

The above resolution process can be obtained from the definition NamespaceHandler, then call the parsemethod resolution.

Then we look at NamespaceHandlerResolver#resolvemethods to see how to get custom NamespaceHandler.

carbon35.png

, Mainly from in this method handlerMappingsto obtain the cache NamespaceHandler. And from the cache getHandlerMappingsmethod, this method will load our top custom spring.handlersfile.

carbon36.png

Spring loaded watching the NamespaceHandlerprocess, let's see the most important BeanDefinitionhow to generate.

Spring has been mentioned above will be used NamespaceHandler.parseto resolve, because we inherited the NamespaceHandlerSupportview inside concrete realization.

carbon37.png

carbon38.png

BeanDefinition will get to register it to a container, and then will pass BeanDefinitiongenerate Bean. This generation process does not belong to the contents of this section, so no overview, interested students can search for themselves.

Dubbo XML Schema extension implementation

Finally, we see how Dubbo XML Schema extensions.

image.png

image.png

You can see the steps Dubbo XML Schema extensions correspond exactly four standard Spring.

to sum up

Full text concludes with a picture.

SpringXML .png extension

Help documentation

Custom-Registration-xsd
XML Schema extension mechanism in Spring

Other platforms .png

Guess you like

Origin www.cnblogs.com/goodAndyxublog/p/11032052.html