The power of Spring is not only that it provides great convenience for Java developers, but also that its open architecture allows users to have the greatest ability to extend Spring.
When we use xml to define spring information, the default element only contains four of beans, bean, import, and alias. Any other tags are custom tags and need to introduce corresponding namespaces, such as context, aop tags, etc.
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
//处理默认的标签元素
parseDefaultElement(ele, delegate);
}
else {
//处理自定义的标签元素
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
The corresponding source code processing is in the parseBeanDefinitions method of the DefaultBeanDefinitionDocumentReader class.
Custom label elements
1. Define People.java
public class People {
private String id;
private int age;
private String name;
private String address;
public People(String id, int age, String name, String address) {
this.id = id;
this.age = age;
this.name = name;
this.address = address;
}
public People() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "People{" +
"id='" + id + '\'' +
", age=" + age +
", name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
2. Define people.xsd, spring.handlers and spring.schemas files in the resources/META-INF directory
people.xsd
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.bobo.com/schema/people"
xmlns:tns="http://www.bobo.com/schema/people"
elementFormDefault="qualified">
<element name="people">
<complexType>
<attribute name ="id" type = "string"/>
<attribute name ="age" type = "int"/>
<attribute name ="name" type = "string"/>
<attribute name ="address" type = "string"/>
</complexType>
</element>
</schema>
spring.handlers
http\://www.bobo.com/schema/people=com.bobo.custom.PeopleNamespaceHandler
spring.schemas
http\://www.bobo.com/schema/people.xsd=META-INF/people.xsd
3. Create the corresponding namespaceHandler class PeopleNamespaceHandler.java
package com.bobo.custom;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
* @author bobo
* @date 2020-10-20
*/
public class PeopleNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
super.registerBeanDefinitionParser("people",new PeopleBeanDefinitionParser());
}
}
4. Create the corresponding BeanDefinitionParser class PeopleBeanDefinitionParser.java
package com.bobo.custom;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* @author bobo
* @date 2020-10-20
*/
public class PeopleBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) {
return People.class;
}
@Override
protected void doParse(Element element, BeanDefinitionBuilder builder) {
String id = element.getAttribute("id");
String age = element.getAttribute("age");
String name = element.getAttribute("name");
String address = element.getAttribute("address");
if (StringUtils.hasLength(id)){
builder.addPropertyValue("id",id);
}
if (StringUtils.hasLength(age)){
builder.addPropertyValue("age",age);
}
if (StringUtils.hasLength(name)){
builder.addPropertyValue("name",name);
}
if (StringUtils.hasLength(address)){
builder.addPropertyValue("address",address);
}
}
}
5. Create the application-context.xml configuration file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:bo="http://www.bobo.com/schema/people"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.bobo.com/schema/people http://www.bobo.com/schema/people.xsd">
<bo:people id="bo" age="20" name="bobo" address="广东省深圳市"></bo:people>
</beans>
6. Create a test class
package com.bobo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
System.out.println(context.getBean("bo"));
}
}
Run output
People{
id='bo', age=20, name='bobo', address='广东省深圳市'}