spring源码扩展点三:自定义配置文件标签

it2023-07-27  73

Spring的强大之处不仅仅在于它为Java开发者提供了极大便利,更在于它的开放式架构,使得用户可以拥有最大扩展Spring的能力。

我们在用xml定义spring信息时,默认的element只包含beans,bean,import,alias这四个,其它任何标签都属于自定义标签,均需要引入相应的命名空间,如:context,aop标签等。

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); } }

对应的源码处理在DefaultBeanDefinitionDocumentReader类的parseBeanDefinitions方法里面。

自定义标签元素

1,定义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,在resources/META-INF目录下定义people.xsd,spring.handlers,spring.schemas文件

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,创建对应的namespaceHandler类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,创建对应的BeanDefinitionParser类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,创建application-context.xml配置文件

<?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,创建测试类

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

运行输出

People{id='bo', age=20, name='bobo', address='广东省深圳市'}
最新回复(0)