本文目录:
前言
我们在 Spring 的 xml 配置文件里经常定义各种各样的配置(tx、mvc、context等),我们将它叫做 Namespace,即:命名空间。如:<tx:advice>
、<dubbo:application>
。
在很多情况下,我们需要为系统提供可配置化支持
,简单的做法可以直接基于 Spring 的标准 Bean 来配置,但配置较为复杂或者需要更多丰富控制的时候,会显得非常笨拙。
一般的做法会用原生态的方式去解析定义好的 xml 文件,然后转化为配置对象,这种方式当然可以解决所有问题,但实现起来比较繁琐, 特别是是在配置非常复杂的时候,解析工作是一个不得不考虑的负担。
1.自定义命名空间步骤
Spring 提供了可扩展 Schema 的支持,这是一个不错的折中方案,完成一个自定义命名那个空间配置,一般需要以下步骤:
- 设计
配置属性
和JavaBean
- 编写
.xsd
文件 - 编写
NamespaceHandler
和BeanDefinitionParser
完成解析工作 - 编写
spring.handlers
和spring.schemas
串联起所有部件 - 在 .xml 配置文件中配置
2.编写Demo来实战
2.1 设计配置属性和JavaBean
首先当然得设计好配置项,并通过 JavaBean 来建模,本例中需要配置 People 实体,配置属性 name 和 age(id是默认需要的)
public class People {
private String id;
private String name;
private Integer age;
}
2.2 编写.xsd文件
为上一步设计好的配置项编写 .xsd 文件,.xsd 是schema 的定义文件,配置的输入和解析输出都是以 xsd 为契约,本例中 xsd 文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
xmlns="http://blog.youkuaiyun.com/cutesource/schema/people"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://blog.youkuaiyun.com/cutesource/schema/people"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" />
<xsd:element name="people">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="age" type="xsd:int" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
关于 xsd:schema 的各个属性具体含义就不作过多解释,可参见连接:XSD - 元素,<xsd:element name=“people”>
对应着配置项节点的名称,因此在应用中会用 people 作为节点名来引用这个配置。<xsd:attribute name=“name” type=“xsd:string” />
和<xsd:attribute name=“age” type=“xsd:int” />
对应着配置项 people 的两个属性名,因此在应用中可以配置 name 和 age 两个属性,分别是 string 和 int 类型。完成后需把 .xsd文件 存放在 classpath 下,一般都放在 META-INF 目录下(本例就放在这个目录下)
2.3 编写 NamespaceHandler 和 BeanDefinitionParser 完成解析工作
下面需要完成解析工作,会用到 NamespaceHandler 和 BeanDefinitionParser 这两个概念。具体说来 NamespaceHandler 会根据<code.schema 和节点名
找到某个 BeanDefinitionParser,然后由 BeanDefinitionParser 完成具体的解析工作。
因此需要分别完成 NamespaceHandler 和 BeanDefinitionParser 的实现类,Spring提供了默认实现类 NamespaceHandlerSupport 和 AbstractSingleBeanDefinitionParser,简单的方式就是去继承这两个类。本例就是采取这种方式:
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class MyNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("people", new PeopleBeanDefinitionParser());
}
}
其中 registerBeanDefinitionParser(“people”, new PeopleBeanDefinitionParser());
就是用来把节点名和解析类联系起来,在配置中引用 people 配置项时,就会用 PeopleBeanDefinitionParser 来解析配置。PeopleBeanDefinitionParser
就是本例中的解析类:
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 PeopleBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
protected Class getBeanClass(Element element) {
return People.class;
}
protected void doParse(Element element, BeanDefinitionBuilder bean) {
//element.getAttribute 就是从配置中取得属性值
String name = element.getAttribute("name");
String age = element.getAttribute("age");
String id = element.getAttribute("id");
if (StringUtils.hasText(id)) {
//bean.addPropertyValue 就是把属性值放到 bean中。
bean.addPropertyValue("id", id);
}
if (StringUtils.hasText(name)) {
bean.addPropertyValue("name", name);
}
if (StringUtils.hasText(age)) {
bean.addPropertyValue("age", Integer.valueOf(age));
}
}
}
2.4 编写 spring.handlers 和 spring.schemas 串联起所有部件
上面几个步骤走下来,你会发现开发好的 handler 与 .xsd文件
还没法让应用感知到,就这样放上去是没法把前面做的工作纳入体系中的。Spring 提供了 spring.handlers 和 spring.schemas 这两个配置文件来完成这项工作。
这两个文件需要我们自己编写,并放入 META-INF 文件夹中,这两个文件的地址必须是 META-INF/spring.handlers 和 META-INF/spring.schemas
,Spring 在启动时,便会默认去载入它们。
spring.handlers 如下所示:
http\://blog.csdn.net/cutesource/schema/people=study.schemaExt.MyNamespaceHandler
以上表示当使用到名为 "http://blog.youkuaiyun.com/cutesource/schema/people"
的 schema 引用时,会通过study.schemaExt.MyNamespaceHandler
来完成解析
spring.schemas 如下所示:
http\://blog.csdn.net/cutesource/schema/people.xsd=META-INF/people.xsd
以上就是载入 .xsd 文件
2.5 在 .xml 文件中配置
到此为止一个简单的自定义配置就完成了,可以在具体应用中使用了。使用方法很简单,和配置一个普通的 spring bean 类似,只不过需要基于我们自定义schema,本例中引用方式如下所示:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cutesource="http://blog.youkuaiyun.com/cutesource/schema/people"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://blog.youkuaiyun.com/cutesource/schema/people http://blog.youkuaiyun.com/cutesource/schema/people.xsd">
<!-- 使用自定义命名空间配置 -->
<cutesource:people id="cutesource" name="Lebron James" age="35"/>
</beans>
其中xmlns:cutesource="http://blog.youkuaiyun.com/cutesource/schema/people"
是用来指定自定义 schema,xsi:schemaLocation
用来指定 .xsd 文件。<cutesource:people id=“cutesource” name=“Lebron James” age=“35”/>
是一个具体的自定义配置使用实例。
2.6 获取我们配置的对象
最后就可以在具体程序中使用 getBean()方式,来载入我们的自定义配置对象了,如:
ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");
People p = (People)ctx.getBean("cutesource");
System.out.println(p.getId());
System.out.println(p.getName());
System.out.println(p.getAge());
输出结果:
cutesource
Lebron James
35
Spring 命名空间自定义,介绍到此为止
如果本文对你有所帮助,那就给我点个赞呗 ^ _ ^
End