工程目录:https://gitee.com/wuhan1/spring-parent/tree/master/spring-12
自定义标签有什么用?
自定义标签可以说是spring为了给类似你我这样的开发人员扩展组件使用的,因为它提供了一个标准的公共可插拔的接口;目前我们都知道spring非常强大,不过实际上除了spring-core和spring-beans外,其他都是通过自定义标签扩展实现的,其次还有一些开源组件也是,如dubbo等。所以,对于想扩展spring组件的小伙伴来说,了解如何自定义标签和相应的原理是必须走的第一步。
如何自定义标签?
1、编写.schemas文件,通知spring容器我们定义的xsd文件在哪里;
2、编写.xsd文件,定义配置时可以使用的属性限制或者说支持的那些属性配置;
3、编写.handlers 文件,扩展NamespaceHandler命名空间注册器和定义及解析器;
4、在xml文件中使用自定义标签
详细例子说明,工程目录
1.定义bean属性,然后在xsd文件中声明
package com.xqc.redis;
public class RedisTag {
private String id;
private String ip;
private Integer port;
private String desc;
public RedisTag(String ip, Integer port, String desc) {
this.ip = ip;
this.port = port;
this.desc = desc;
}
public RedisTag() {
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public RedisTag(String ip, Integer port) {
this.ip = ip;
this.port = port;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
xsd文件
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/schema/xqc"
xmlns="http://www.example.org/schema/xqc"
elementFormDefault="qualified">
<xsd:element name="redis">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string" />
<xsd:attribute name="ip" type="xsd:string" />
<xsd:attribute name="port" type="xsd:string" />
<xsd:attribute name="desc" type="xsd:string" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
2.通过spring.shemas指定xsd文件
http\://www.example.org/schema/xqc.xsd=META-INF/xqc.xsd
类似与key=value的形式,如果找不到会去网络上下载。
3.通过spring.handlers指定自定义标签的解析器入口
http\://www.example.org/schema/xqc=com.xqc.namespace.RedisNamespaceHandler
需要实现NamespaceHandler接口,我们继承的它的实现类NamespaceHandlerSupport
import com.xqc.parse.RedisBeanDefinitionParser;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class RedisNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
this.registerBeanDefinitionParser("redis",new RedisBeanDefinitionParser());
}
}
在init方法里使用我们自定义的解析器,
4.自定义的解析器需要集成BeanDefinitionParser接口,本例中集成的是它的子接口AbstractSingleBeanDefinitionParser
package com.xqc.parse;
import com.xqc.redis.RedisTag;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
public class RedisBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
String ip = element.getAttribute("ip");
String port = element.getAttribute("port");
String desc = element.getAttribute("desc");
builder.addPropertyValue("ip",ip);
builder.addPropertyValue("port",Integer.parseInt(port));
builder.addPropertyValue("desc",desc);
}
@Override
protected Class<?> getBeanClass(Element element) {
return RedisTag.class;
}
}
v
按照上面的步骤,一个简单的自定义解析器就完成了,我们可以把工程打成jar包,然后在其他工程里配置使用,本例中我们就在自己当前的工程中解析使用
在applicationContext.xml中声明
<!--suppress SpringFacetInspection -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xqc="http://www.example.org/schema/xqc"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
http://www.example.org/schema/xqc http://www.example.org/schema/xqc.xsd">
<xqc:redis id="redis" ip="localhost" port="6379" desc="redis配置"></xqc:redis>
</beans>
通过容器获取配置

遇到的问题总结,按照我们上面的格式如果在bean和xsd中没有声明ID,这样使用
报错
翻译报错信息:
、