“This is the second day of my participation in the First Challenge 2022.
In addition to Spring’s default Namespace in the Spring XML configuration file, today we will look at how to customize a Namespace
1. Spring custom XML Namespace principle
Throughout the Spring container to start the process again, but at the time of loading the Bean definition, an XML configuration file is called AbstractXmlApplicationContext# loadBeanDefinitions method to load Bean definitions in the XML. Then XmlBeanDefinitionReader parses the XML from the set default location or the specified location into a Document into memory. BeanDefinitionDocumentReader responsible for each Element in the XML Document.
During the process, the mapping between the Namespace and the XSD file configured in the meta-INF/Spring. schemas is read and verified
In the process of parsing, the Namespace is determined to be the Spring default Namespace or the user-defined Namespace
-
Spring defaults to Element handling
The default Element: import, alias, beans, beans, these are provided by default DefaultBeanDefinitionDocumentReader parsing
-
Custom Element handling
Handlers by getting the handler class configured for a Namespace in the meta-INF/Spring. handlers file. The Namespace handler class implements NamespaceHandler or NamespaceHandlerSupport.
The Element is then parsed by calling the NamespaceHandler#parse method of the NamespaceHandler concrete instance.
2. Spring custom XML Namespace practice
Define an Element that has the same functionality as Spring’s default bean. This Element can be called mxsmBean.
2.1 XSD definitions
The XSD file defines what properties the mxsmBean needs to have.
<xsd:schema xmlns="https://github.com/mxsm/schema/mxsm" (1)
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="https://github.com/mxsm/schema/mxsm"> (2)
<xsd:import namespace="http://www.springframework.org/schema/beans" />
<xsd:element name="mxsmBean">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="class" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Copy the code
(1) and (2) add their own Namescape, where XSD is stored as follows:
2.2 Writing the Implementation of NamespaceHandler interface
This interface is mainly used to handle our corresponding Element. For example, in github.com/mxsm/schema… Now I’m just defining the Application Element so I only need to parse this one.
NamespaceHandlerSupport is an abstract method that implements part of the NamespaceHandler interface. Normally we implement the NamespaceHandlerSupport class
public class MxsmSchemaHandler extends NamespaceHandlerSupport {
@Override
public void init(a) {
registerBeanDefinitionParser("mxsmBean".new MxsmBeanDefinitionParser());
// Call multiple elements if there are multiple elements}}public class MxsmBeanDefinitionParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
String aClass = element.getAttribute("class");
System.out.println(aClass);
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(aClass);
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
parserContext.getRegistry().registerBeanDefinition(element.getAttribute("name"), beanDefinition);
returnbeanDefinition; }}Copy the code
Each corresponding tag corresponds to a parser class that implements the BeanDefinitionParser interface.
2.3 Configuring meta-INF /spring.schemas and meta-INF /spring.handlers file configuration
Spring. schemas Function: Configure the storage location of the XSD file of a user-defined Namespace
https\://github.com/mxsm/schema/mxsm/mxsm.xsd=com/github/mxsm/xml/xsd/mxsm.xsd
Copy the code
Handlers Function: Configure a NamespaceHandler for a user-defined Namespace
https\://github.com/mxsm/schema/mxsm=com.github.mxsm.handler.MxsmSchemaHandler
Copy the code
The location of storage in the project is shown as follows:
2.4 Introducing custom Elements in the Spring Application.xml file
Create the XML file for the Spring application.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mxsm="https://github.com/mxsm/schema/mxsm" (1)
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd https://github.com/mxsm/schema/mxsm (2) https://github.com/mxsm/schema/mxsm/mxsm.xsd (3) http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<mxsm:mxsmBean class="com.github.mxsm.bean.MxsmBeanTest" name="test"/>
</beans>
Copy the code
(1), (2), (3) these three need to be added when used. At this point, the customization steps are complete. The next step is to verify that we can inject this class into the Spring container. Here we write a test code to verify:
public class App {
public static void main( String[] args ) {
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
//System.out.println(context.getBean("aaaa",String.class));
MxsmBeanTest test = context.getBean("test", MxsmBeanTest.class); System.out.println(test); MxsmBeanTest bean = context.getBean(MxsmBeanTest.class); System.out.println(bean); System.out.println(test==bean); }}Copy the code
Then run to see the result:
It can be seen from the running result that the corresponding instance of MxsmBeanTest can be obtained, and it is still a singleton. So the definition that we registered in the Spring container when we created the default gets the class instance as a singleton by default.
Full code address: github.com/mxsm/spring…
3. Summary
- Before you can customize an extension, first you need to know what the Element you are extending is for, and then parse it according to its purpose. For example, the mxsmBean above is intended to implement a simplified version of Spring’s default Bean functionality.
- Namespace XSD file writing, the writing of the need to understand the XSD (tutorial reference: www.w3school.com.cn/schema/sche.)
- NamespaceHandler and BeanDefinitionParser interfaces need to be implemented at the interface level, which were used previously.
- Add configurations in the meta-INF /spring.schemas and meta-INF/spring.Handlers files, and Spring loads the configurations in these files for parsing by default.
- Import the corresponding custom Namespace into the Spring XML configuration file.
Here’s how to customize a namespace, how to do it, and how Spring interprets it. For more details, visit the Spring website (docs. Spring. IO /spring-fram… Util (spring-util.xsd). You can learn from these. In this way, you can better understand and understand the process of customization.