Spring实践之自定义命名空间并解析
自定义一个命名空间
1、新建一个空项目,在 resources/META-INF 目录下新建一个 spring.handlers 文件,内容如下:
http\://open.harvey.com/schema/dog=com.harvey.open.annotation.spring.DogNamespaceHandler
文件内容为一个键值对。
key 为自定义命名空间:http://open.harvey.com/schema/dog
value 为自定义命名空间对应的 NameSpaceHandler :com.harvey.open.annotation.spring.DogNamespaceHandler
2、在 resources/META-INF 目录下新建一个 spring.schemas 文件,内容如下:
http\://open.harvey.com/schema/dog/dog-1.0.xsd=./com/harvey/open/dog/config/dog-1.0.xsd
文件内容为一个键值对。
key 为 schema 的 Url:http://open.harvey.com/schema/dog/dog-1.0.xsd
value 为本地 schema 路径:./com/harvey/open/dog/config/dog-1.0.xsd
3、对应第1步 spring.handlers 内容中的 value,在 com.harvey.open.annotation.spring 目录下新建 DogNamespaceHandler.java,内容如下:
package com.harvey.open.annotation.spring;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class DogNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
// 注册一个自定义的解析器, 用于解析命名空间下的annotation节点
registerBeanDefinitionParser("annotation", new DogAnnotationDefinitionParser());
}
}
这里用到了org.springframework.beans.factory.xml.NamespaceHandlerSupport,所以需要导入依赖:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.0.2.RELEASE</version> </dependency>
新建 DogAnnotationDefinitionParser.java,内容如下:
package com.harvey.open.annotation.spring;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
public class DogAnnotationDefinitionParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(DogBean.class);
MutablePropertyValues mutablePropertyValues = beanDefinition.getPropertyValues();
// 添加name属性
if (element.hasAttribute("name")) {
mutablePropertyValues.addPropertyValue("name", element.getAttribute("name"));
}
// 添加package属性
if (element.hasAttribute("package")) {
mutablePropertyValues.addPropertyValue("package", element.getAttribute("package"));
}
String id = element.getAttribute("id");
// 拿到注册表, 注册BeanDefinition
parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
return beanDefinition;
}
}
其中用到的 DogBean 代码如下:
package com.harvey.open.annotation.spring;
public class DogBean {
private String name;
private String basePackage;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPackage() {
return basePackage;
}
public void setPackage(String basePackage) {
this.basePackage = basePackage;
}
@Override
public String toString() {
return "DogBean{" +
"name='" + name + '\'' +
", basePackage='" + basePackage + '\'' +
'}';
}
}
4、对应第2步 spring.schemas 内容中的 value,在 resource下新建目录:com.harvey.open.dog.config,在目下新建文件 dog-1.0.xsd,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://open.harvey.com/schema/dog"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://open.harvey.com/schema/dog"
elementFormDefault="qualified">
<xsd:complexType name="annotationType">
<xsd:attribute name="id" type="xsd:ID">
<xsd:annotation>
<xsd:documentation><![CDATA[ The unique identifier for a bean. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="name" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[ The name of bean. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="package" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[ The scan package. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:element name="annotation" type="annotationType">
<xsd:annotation>
<xsd:documentation><![CDATA[ The annotation config ]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:schema>
至此,一个简单的自定义命名空间已经完成,我们将该项目打成 jar包到本地仓库。
全部文件的结构图如下:
使用自定义命名空间
上面我们将自定义命名空间项目打成 jar 包到本地仓库,下面我们来简单的使用一下。
1、在 maven 中添加依赖
<dependency>
<groupId>com.harvey</groupId>
<artifactId>open-harvey-annotation</artifactId>
<version>1.0.0</version>
</dependency>
2、在配置文件中使用自定义命名空间,例如:
3、写个 main 方法测试一下
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath*:applicationContext.xml");
System.out.println(applicationContext.getBean("dog"));
}
}
运行后输出:DogBean{name='Spike', basePackage='com.harvey.open.service'}