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.
- Creating XML Schema file, because the file suffix xsd, referred to below as XSD file.
- Writing implements one or more
BeanDefinitionParser
. - Write
NamespaceHandler
implementation class. - Sign up
NamespaceHandler
and 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 AbstractSingleBeanDefinitionParser
and 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 NamespaceHandlerSupport
the abstract class, implement init
methods. 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.handlers
Specifies the NamespaceHandler
full 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:
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 BeanDefinitionDocumentReader
reading the label inside the beans all configurations, through this process will BeanDefinitionParserDelegate#parseCustomElement
resolve the custom elements.
The above resolution process can be obtained from the definition NamespaceHandler
, then call the parse
method resolution.
Then we look at NamespaceHandlerResolver#resolve
methods to see how to get custom NamespaceHandler
.
, Mainly from in this method handlerMappings
to obtain the cache NamespaceHandler
. And from the cache getHandlerMappings
method, this method will load our top custom spring.handlers
file.
Spring loaded watching the NamespaceHandler
process, let's see the most important BeanDefinition
how to generate.
Spring has been mentioned above will be used NamespaceHandler.parse
to resolve, because we inherited the NamespaceHandlerSupport
view inside concrete realization.
BeanDefinition will get to register it to a container, and then will pass BeanDefinition
generate 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.
You can see the steps Dubbo XML Schema extensions correspond exactly four standard Spring.
to sum up
Full text concludes with a picture.
Help documentation
Custom-Registration-xsd
XML Schema extension mechanism in Spring