Spring extensible XML Configuration Mechanism Practice

Source: Internet
Author: User
Tags xmlns zookeeper

Students who have used Dubbo should be familiar with the following configuration:

<beans xmlns= "Http://www.springframework.org/schema/beans"
    xmlns:xsi= "http://www.w3.org/2001/ Xmlschema-instance "
    xmlns:dubbo=" Http://code.alibabatech.com/schema/dubbo "
    xsi:schemalocation="/http/ Www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http ://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd ">
    <!--provider application information , for calculating dependencies
    --<dubbo:application name= "Hello-world-app"  />

    <!--using ZK to expose the service address to the registry--
    <dubbo:registry address= "zookeeper://127.0.0.1:2181"/>

    <!--with Dubbo protocol on port
    20880 <dubbo:protocol name= "Dubbo" port= "20880"/>

    <bean id= "Demoservice" class= " Com.alibaba.dubbo.demo.provider.DemoServiceImpl "/>

    <dubbo:service interface=" Com.alibaba.dubbo.demo.DemoService "ref=" Demoservice "/>

</beans>

We provide RPC services through Dubbo:service, and everything is commonplace. But have you ever wondered what Dubbo:service really is. How spring parses it and injects it into the container.

This article focuses on the spring Framework's schema-style XML extension mechanism, which allows us to add our own tags to the spring.xml through the XML extension mechanism provided by spring, which will then help us to parse and incorporate into our own management scope. Environment Configuration

JDK 1.7
Spring 4.3.3.RELEASE
Maven 3.3
Idea Example

By learning Spring Extensible XML, I wrote a demo sample like Dubbo Custom label for everyone to learn, the project structure is as follows:

Finally, we can introduce our custom tags in the spring configuration file as follows:

<?xml version= "1.0" encoding= "UTF-8"?> <beans xmlns= "Http://www.springframework.org/schema/beans" Xmlns:xs
       I= "Http://www.w3.org/2001/XMLSchema-instance" xmlns:context= "Http://www.springframework.org/schema/context" Xmlns:rpc= "Http://www.bytebeats.com/schema/rpc" xsi:schemalocation= "Http://www.springframework.org/schema/beans Http://www.springframework.org/schema/beans/spring-beans.xsd Http://www.springframework.org/schema/context http ://www.springframework.org/schema/context/spring-context-4.0.xsd HTTP://WWW.BYTEBEATS.COM/SCHEMA/RPC/http
    Www.bytebeats.com/schema/rpc/rpc.xsd "> <rpc:registry id=" ZK "protocol=" Zookeeper "address=" 127.0.0.1 "/> <rpc:protocol id= "Hessian" name= "Hessian" port= "9001"/> <rpc:service id= "Rpcservice" ref= "HelloService" int Erface= "Com.bytebeats.spring4.extension.service.IHelloService" timeout= "retries=" 1 "></rpc:service > <rpc:ref id= "Accountservice" InterfaCe= "Com.bytebeats.spring4.extension.service.IAccountService" retries= "0" check= "false"/> <bean id= " HelloService "class=" Com.bytebeats.spring4.extension.service.impl.HelloServiceImpl "/> </beans>
1. Define XML Schema

First, we need to define an XSD file to declare the XML tag element, which is rpc.xsd in this article, as follows:

<?xml version= "1.0" encoding= "UTF-8"?> <xsd:schema xmlns= "Http://www.bytebeats.com/schema/rpc" xmlns: Xsd= "Http://www.w3.org/2001/XMLSchema" xmlns:beans= "Http://www.springframework.org/schema/beans" t Argetnamespace= "Http://www.bytebeats.com/schema/rpc" elementformdefault= "qualified" ATTRIBUTEFORMD efault= "Unqualified" > <xsd:import namespace= "Http://www.springframework.org/schema/beans"/> <xsd:com Plextype name= "Abstractconfig" > <xsd:choice minoccurs= "0" maxoccurs= "unbounded" > <xsd:elem ENT ref= "beans:property" minoccurs= "0" maxoccurs= "unbounded"/> </xsd:choice> <xsd:anyattribut
        E namespace= "# #other" processcontents= "lax"/> </xsd:complexType> <xsd:element name= "service" > <xsd:complexType> <xsd:complexContent> <xsd:extension base= "Abstractconfig
                  ">  <xsd:choice minoccurs= "0" maxoccurs= "unbounded" > <xsd:element ref= "Beans:property" MinO ccurs= "0" maxoccurs= "unbounded"/> </xsd:choice> <xsd:attribute name= "
                    ID "type=" xsd:id "/> <xsd:attribute name=" ref "Type=" xsd:string "use=" required "/> <xsd:attribute name= "interface" type= "xsd:string" use= "required"/> <xsd:attribute na Me= "group" type= "xsd:string" use= "optional"/> <xsd:attribute name= "Registry" type= "Xsd:string" u
                    se= "optional"/> <xsd:attribute name= "version" Type= "xsd:string" use= "optional"/> <xsd:attribute name= "Timeout" type= "xsd:string" use= "optional"/> <xsd:attribute name= "Retries" type= "xsd:string" use= "optional"/> <xsd:attribute name= "Async" type= "Xsd:boolean" use=
        "Optional"/>        </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:eleme
                nt> <xsd:element name= "ref" > <xsd:complexType> <xsd:complexContent> <xsd:extension base= "Abstractconfig" > <xsd:choice minoccurs= "0" maxoccurs= "unbounded"
                    > <xsd:element ref= "beans:property" minoccurs= "0" maxoccurs= "unbounded"/> </xsd:choice> <xsd:attribute name= "id" type= "xsd:id"/> <xsd: Attribute Name= "interface" type= "xsd:string" use= "required"/> <xsd:attribute name= "group" type= " Xsd:string "use=" optional "/> <xsd:attribute name=" Registry "type=" Xsd:string "use=" optional "/&gt
                    ; <xsd:attribute name= "Version" Type= "xsd:string" use= "optional"/> <xsd:attribute name= "Timeout "Type= "xsd:string" use= "optional"/> <xsd:attribute name= "retries" type= "xsd:string" use= "optional "/> <xsd:attribute name=" Async "type=" Xsd:boolean "use=" optional "/> <x Sd:attribute name= "Check" type= "Xsd:boolean" use= "optional"/> </xsd:extension> </x
        sd:complexcontent> </xsd:complexType> </xsd:element> <xsd:element name= "Registry" > <xsd:complexType> <xsd:complexContent> <xsd:extension base= "abstractconf  IG "> <xsd:choice minoccurs=" 0 "maxoccurs=" unbounded "> <xsd:element
                    ref= "Beans:property" minoccurs= "0" maxoccurs= "unbounded"/> </xsd:choice> <xsd:attribute name= "id" type= "xsd:id"/> <xsd:attribute name= "protocol" type= "Xsd:string"
    use= "Required"/>                <xsd:attribute name= "Address" type= "xsd:string" use= "required"/> <xsd:attribu Te name= "username" type= "xsd:string" use= "optional"/> <xsd:attribute name= "password" type= "xsd:s
                Tring "use=" optional "/> <xsd:attribute name=" Check "type=" Xsd:boolean "use=" optional "/> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:el
                ement> <xsd:element name= "protocol" > <xsd:complexType> <xsd:complexContent> <xsd:extension base= "Abstractconfig" > <xsd:choice minoccurs= "0" maxoccurs= "un
                    Bounded "> <xsd:element ref=" beans:property "minoccurs=" 0 "maxoccurs=" unbounded "/>
                    </xsd:choice> <xsd:attribute name= "id" type= "xsd:id"/> <xsd:attribute name= "Name "type=" xsd:string "use=" required "/> <xsd:attribute name=" port "type=" xsd:string "use=" Requi Red "/> <xsd:attribute name=" host "type=" xsd:string "use=" optional "/> </xsd :extension> </xsd:complexContent> </xsd:complexType> </xsd:element> </xsd :schema>

About the XML Schema is not detailed here, you can refer to w3school XML Schema Introduction 2, define the parser

Define a Beandefinitionparser responsible for parsing the XML, as follows:

Package com.bytebeats.spring4.extension.xml;
Import Com.bytebeats.spring4.extension.domain.RpcServiceBean;
Import org.springframework.beans.factory.support.AbstractBeanDefinition;
Import Org.springframework.beans.factory.support.BeanDefinitionBuilder;
Import Org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
Import Org.springframework.beans.factory.xml.ParserContext;
Import Org.springframework.util.StringUtils;

Import org.w3c.dom.Element;  /** * ${description} * * @author Ricky Fung * @create 2016-11-23 11:50 * public class Rpcservicebeandefinitionparser  Extends Abstractbeandefinitionparser {@Override protected abstractbeandefinition parseinternal (element element,
    ParserContext parsercontext) {return parsecomponet (element, parsercontext); } private Abstractbeandefinition Parsecomponet (element element, ParserContext ParserContext) {Beandefinitio NBuilder builder = beandefinitionbuilder.rootbeandefinition (Rpcservicebean.class);
        String id = element.getattribute ("id");
        if (Stringutils.hastext (ID)) {builder.addpropertyvalue ("id", id);
        } String ref = Element.getattribute ("ref");

        Builder.addpropertyvalue ("ref", ref);
        String InterfaceName = Element.getattribute ("interface");

        Builder.addpropertyvalue ("InterfaceName", InterfaceName);
        String Group = element.getattribute ("group");
        if (Stringutils.hastext (group)) {Builder.addpropertyvalue ("group", group);
        } String Registry = Element.getattribute ("registry");
        if (Stringutils.hastext (registry)) {Builder.addpropertyvalue ("registry", registry);
        } String Version = Element.getattribute ("version"); if (Stringutils.hastext (version)) {Builder.addpropertyvalue ("version", version)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.