通常情况下,我们只需要按照系统标签的格式去配置bean即可,但是复杂的情况下,需要我们采取自定义标签。
整体流程
Spring 提供了可扩展 Schema 的支持,这是一个不错的折中方案,扩展 Spring 自定义标签配置大致需要以下几个步骤:
- 创建一个需要扩展的组件;
 - 定义一个 XSD 文件来描述组件内容;
 - 创建一个文件,实现 BeanDefinitionParser 接口,用来解析 XSD 文件中的定义和组件定义;
 - 创建一个 Handler 文件,扩展自 NamespaceHandlerSupport,目的是将组件注册到 Spring 容器;
 - 编写 spring.handlers 和 spring.schemas文件;
 - 测试使用自定义标签。
自定义组件
自定义个组件,用于接收标签的配置 . ```java package cn.lichenghao.customtag; 
public class Keyboard { private String name; private String color;
public Keyboard() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}@Overridepublic String toString() {return "Keyboard{" +"name='" + name + '\'' +", color='" + color + '\'' +'}';}
}
<a name="qXigy"></a>## 定义 xsd定义一个 xsd 文件,来描述我们的组件。可以参考系统自带的写,比如 spring-tx.xsd。<br />这里需要注意格式:http://www.lichenghao.cn/schema/{自定义命名}/spring-{自定义命令},建议前后两个一致。```xml<?xml version="1.0" encoding="UTF-8"?><schema xmlns="http://www.w3.org/2001/XMLSchema"targetNamespace="http://www.lichenghao.cn/schema/mytag/spring-mytag"xmlns:tns="http://www.lichenghao.cn/schema/mytag/spring-mytag"elementFormDefault="qualified"><element name="keyboard"><complexType><attribute name="id" type="string"/><attribute name="name" type="string"/><attribute name="color" type="string"/></complexType></element></schema>
定义 DefinitionParser
创建 DefinitionParser 来解析组件
package cn.lichenghao.customtag;import org.springframework.beans.factory.support.BeanDefinitionBuilder;import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;import org.springframework.util.StringUtils;import org.w3c.dom.Element;public class KeyboardDefinitionParser extends AbstractSingleBeanDefinitionParser {@Overrideprotected Class<?> getBeanClass(Element element) {return Keyboard.class;}@Overrideprotected void doParse(Element element, BeanDefinitionBuilder builder) {String name = element.getAttribute("name");if (StringUtils.hasText(name)) {builder.addPropertyValue("name", name);}String color = element.getAttribute("color");if (StringUtils.hasText(color)) {builder.addPropertyValue("color", color);}}}
定义 NamespaceHandlerSupport
创建 NamespaceHandlerSupport 注册组件
package cn.lichenghao.customtag;import org.springframework.beans.factory.xml.NamespaceHandlerSupport;public class MyNameSpaceHandler extends NamespaceHandlerSupport {@Overridepublic void init() {registerBeanDefinitionParser("keyboard", new KeyboardDefinitionParser());}}
定义 spring.handlers、spring.schemas
编写配置文件,放在 META-INF 文件夹下。
spring.handlers
http\://www.lichenghao.cn/schema/mytag/spring-mytag=cn.lichenghao.customtag.MyNameSpaceHandler
spring.schemas
http\://www.lichenghao.cn/schema/mytag/spring-mytag.xsd=META-INF/spring-mytag.xsd
启动测试
<?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:my="http://www.lichenghao.cn/schema/mytag/spring-mytag"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.lichenghao.cn/schema/mytag/spring-mytaghttp://www.lichenghao.cn/schema/mytag/spring-mytag.xsd"><!--自定义标签--><my:keyboard id="cherry" name="cherry" color="black" /></beans>
xmlns:my=”http://www.lichenghao.cn/schema/mytag/spring-mytag“  自定义标签前缀,可以是任何内容。
http://www.lichenghao.cn/schema/mytag/spring-mytag、
http://www.lichenghao.cn/schema/mytag/spring-mytag.xsd
映射到 spring.handlers 文件和 spring.schemas 文件。
单元测试
@DisplayName("测试自定义标签")@Testpublic void customTagTest() {ClassPathXmlApplicationContext context= new ClassPathXmlApplicationContext("customtag/keyboard.xml");Keyboard keyboard = context.getBean(Keyboard.class);System.out.println(keyboard);}
小结
Spring 加载自定义的大致流程是遇到自定义标签然后就去 spring.handlers 和 spring.schemas 中去找对应的 handler 和 XSD,默认位置是/META-NF/ 下,进而有找到对应的 handler 以及解析元素的 Parser,从而完成了整个自定义元素的解析。
