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 "/>
; <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)