Spring具有一个基于架构的扩展机制,可以使用xml文件定义和配置bean。本文将介绍如何编写自定义XML bean的解析器,以及自定义注解,并用实例来加以说明。
自定义配置文件标签从Spring version 2.0开始就有,现在的很多项目中大量使用了Spring注解方式来开发,使得自定义Spring标签看起来不是很流行,不过在灵活的架构项目中或者你想简化项目配置,自定义标签还是一种不错架构策略。
本文就使用Maven,Spring5来举个例子,后期还会增加两篇文章来介绍自定义配置文件在简化项目配置中的应用。
想来张项目截图了解下工程结构:
自定义标签大致分为以下几个步骤:
1、Authoring an XML schema to describe your custom element(s). 自定义一个XML schema(liqi-spring-customize-tag.xsd)它的作用是规范你的自定义标签。
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.ieflex.com/schema/lct"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://www.ieflex.com/schema/lct"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" />
<xsd:element name="dateformat">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="lenient" type="xsd:boolean"/>
<xsd:attribute name="pattern" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
2、Coding a custom NamespaceHandler implementation (this is an easy step, don’t worry).自定义一个命名空间处理类,这个类需要继承spring的NamespaceHandlerSupport,你所有的自定义标签命名空间,和业务处理类都需要在初始化init方法里注册。
package com.ieflex.fw.handler;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import com.ieflex.fw.parser.DateFormatDefinitionParser;
/**
* <p><code>LctNamespaceHandler</code> for the <code>lct</code> namespace.
*
* @since 1.0
*/
public class LctNamespaceHandler extends NamespaceHandlerSupport {
public LctNamespaceHandler() {
super();
}
@Override
public void init() {
registerBeanDefinitionParser("dateformat", new DateFormatDefinitionParser());
}
}
3、Coding one or more BeanDefinitionParser implementations (this is where the real work is done).写一个BeanDefinitionParser类,你的自定义标签都需要实现什么样操作都写在这里就可以了。
package com.ieflex.fw.parser;
import java.text.SimpleDateFormat;
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 DateFormatDefinitionParser extends AbstractSingleBeanDefinitionParser {
protected Class getBeanClass(Element element) {
return SimpleDateFormat.class;
}
protected void doParse(Element element, BeanDefinitionBuilder bean) {
// this will never be null since the schema explicitly requires that a
// value be supplied
String pattern = element.getAttribute("pattern");
bean.addConstructorArgValue(pattern);
// this however is an optional property
String lenient = element.getAttribute("lenient");
if (StringUtils.hasText(lenient)) {
bean.addPropertyValue("lenient", Boolean.valueOf(lenient));
}
}
}
4、Registering the above artifacts with Spring (this too is an easy step).将你写好的自定标签命名规则和业务处理,一起注册到META-INF下,spring初始化的时候会根据spring.handlers和spring.schemas的定义去加载实现。
在META-INF下面创建两个文件spring.handlers和spring.schemas,内容如下:
spring.handlers:
http\://www.ieflex.com/schema/lct=com.ieflex.fw.handler.LctNamespaceHandler
spring.schemas:
http\://www.ieflex.com/schema/lct.xsd=liqi-spring-customize-tag.xsd
5、官方例子
6、工程下载