作为一般的应用程序开发人员,扩展spring的标签意义不大。
但如果你是一个平台开发人员,则很有必要拥有一套自己的标签,提供给应用开发人员使用,因为走秀网需要搭建一个mq平台,简化配置信息,所以要扩展spring的标签。
- <xiu:datasource id= "datasource"
- databaseType= "oracle"
- ip= "192.168.80.82"
- port= "1521"
- databaseName= "orcl"
- userName= "xiu_sms"
- password= "xiu_sms"
- />
- <xiu:ehCache id= "xiu"
- cache= "true"
- maxElements= "100000"
- timeToIdleSeconds= "120"
- timeToLiveSeconds= "120"
- overflowToDisk= "true"
- />
上面的代码中配置了两个组件,datasource和cache组件,相比普通的bean和propertiy方式,很显然,这种配置方式更直观,更易读,更重要的是,如果作为组件发布,使用者也可以很方便快捷的开始使用,而不需要关心组件的任何实现细节。
扩展spring自定义标签配置大致需要一下几个步骤(前提是要把spring的core包加入项目中)
1、创建一个需要扩展的组件
2、定义一个xsd文件描述组件内容
3、创建一个文件,实现BeanDefinitionParser接口,用来解析xsd文件中的定义和组件定义
4、创建一个Handler文件,扩展自NamespaceHandlerSupport,目的是将组件注册到Spring容器
5、编写spring.handlers和spring.schemas文件
提供一个简单的例子,来说明如何去扩展一个Spring配置,需求如下:使用自定义标签定义一个简单的bean,这个bean有一个或多个属性,标签定义完成后,可以在其他项目中用自定义标签来定义该bean。
首先,创建一个需要扩展的组件,在这里只是一个简单的bean,bean中有3个属性。
代码:
package com.xiu.tag;
public class DataSourceBean {
private Stringurl;
private Stringdbname;
private StringmaxIndex;
public StringgetUrl() {
return url;
}
public voidsetUrl(String url) {
this.url =url;
}
public StringgetDbname() {
returndbname;
}
public voidsetDbname(String dbname) {
this.dbname =dbname;
}
public StringgetMaxIndex() {
returnmaxIndex;
}
public voidsetMaxIndex(String maxIndex) {
this.maxIndex= maxIndex;
}
}
然后,建立一个xsd文件,来描述这个bean
data.xsd
代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schemaxmlns="http://www.xiu.com/schema/data"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://www.xiu.com/schema/data"
elementFormDefault="qualified"attributeFormDefault="unqualified">
<xsd:import
namespace="http://www.springframework.org/schema/beans">
</xsd:import>
<xsd:elementname="DataSourceBean">
<xsd:complexType>
<xsd:complexContent>
<xsd:extensionbase="beans:identifiedType">
<xsd:attributename="url" type="xsd:string"
default="www.xiu.com"/>
<xsd:attributename="dbname" type="xsd:string"
default="orcl"/>
<xsd:attributename="maxIndex" type="xsd:string"
default="100" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
在上面的xsd文件描述了一个新的targetNamespace,并在这个空间中定义了一个name为DataSourceBean的element,one有三个属性url,dbnamne,maxIndex类型为string,而且都有默认值.xsd文件是xml DTD的替代者,使用XML Schema语言进行编写,这里对xsd schema不做太多解释,有兴趣可以参考相关的资料。
创建一个Java文件,该文件实现了BeanDefinitionParser接口,用来解析xsd文件中的定义并注册到组件中
XiuBeanDefinitionParser.java
代码如下:
package com.xiu.tag;
importorg.springframework.beans.factory.config.BeanDefinition;
importorg.springframework.beans.factory.config.BeanDefinitionHolder;
importorg.springframework.beans.factory.support.BeanDefinitionReaderUtils;
importorg.springframework.beans.factory.support.RootBeanDefinition;
importorg.springframework.beans.factory.xml.BeanDefinitionParser;
importorg.springframework.beans.factory.xml.ParserContext;
importorg.w3c.dom.Element;
public classXiuBeanDefinitionParser implements BeanDefinitionParser {
public BeanDefinition parse(Elementelement, ParserContext parserContext) {
// 设置 Bean Class也就是DataSourceBean
RootBeanDefinition rdef = newRootBeanDefinition();
rdef.setBeanClass(DataSourceBean.class);
// 注册id属性,没人是有id属性,在xsd文件中可以不用声明
// 但是在注册时必须要注入
String id =element.getAttribute("id");
BeanDefinitionHolderidDefinitionHolder = new BeanDefinitionHolder(
rdef, id);
BeanDefinitionReaderUtils.registerBeanDefinition(idDefinitionHolder,
parserContext.getRegistry());
// 注册url属性
String url =element.getAttribute("url");
BeanDefinitionHolderurlDefinitionHolder = new BeanDefinitionHolder(
rdef, url);
BeanDefinitionReaderUtils.registerBeanDefinition(urlDefinitionHolder,
parserContext.getRegistry());
rdef.getPropertyValues().addPropertyValue("url",url);
// 注册dbname属性
String dbName =element.getAttribute("dbname");
BeanDefinitionHolderdbNameDefinitionHolder = new BeanDefinitionHolder(
rdef, dbName);
BeanDefinitionReaderUtils.registerBeanDefinition(dbNameDefinitionHolder,
parserContext.getRegistry());
rdef.getPropertyValues().addPropertyValue("dbname",dbName);
// 注册maxIndex属性
String maxIndex =element.getAttribute("maxIndex");
BeanDefinitionHoldermaxIndexDefinitionHolder = new BeanDefinitionHolder(
rdef, maxIndex);
BeanDefinitionReaderUtils.registerBeanDefinition(maxIndexDefinitionHolder,
parserContext.getRegistry());
rdef.getPropertyValues().addPropertyValue("maxIndex",maxIndex);
return rdef;
}
}
上面的代码仅仅实现了一个方法publicBeanDefinition parse(Element element, ParserContext parserContext),设置相关的Bean Class,解析了对应的xsd文件,并将解析的内容注册到上下文中,同时返回一个BeanDefinition对象(BeanDefinition是Spring的bean定义,提供了bean部分的操作方法,如isSingleton()、isLazyInit()等)。
注意,id属性是一个默认的属性,可以不在xsd文件中描述,但是需要注册它,否则将无法通过getBean方法获取标签定义的bean,也无法被其他bean引用。
另外,下面代码是给bean的属性赋值,这个是不可缺少的,否则在使用标签定义时将无法获取bean属性的值。
代码
rdef.getPropertyValues().addPropertyValue("maxIndex",maxIndex);
然后为组件编写一个Handler文件,扩展自NamespaceHandlerSupport,它的作用是将组件注册到Spring容器
XiuNameSpaceHandler.java
代码如下:
package com.xiu.tag;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public classXiuNameSpaceHandler extends NamespaceHandlerSupport{
public void init() {
registerBeanDefinitionParser("DataSourceBean",newXiuBeanDefinitionParser());
}
}
实际执行的过程只有一句代码,注册了一个名字为DataSourceBean的扩展配置,包含了XiuBeanDefinitionParser 所parser相关xsd的内容。
到了这里,一个Spring扩展标签已经完成,但是我们目前还没办法使用它,Spring没那么聪明,它无法知道我们在什么地方定义了哪些扩展标签,这些标签将被谁解析,这个过程要我们通过一些文件来告知Spring知道,它们就是spring.handlers和spring.schemas,它们放在META-INF目录中,Spring.jar的META-INF目录中也有同名的文件,它们的文件内容基本上是相似的,而Spring在执行过程中,如果发现其他jar文件的META-INF文件夹中包含有这两个文件,Spring将会合并它们。
spring.schemas
代码
- http\://www.xiu.com/schema/data.xsd=com/xiu/tag/data.xsd // http后面的斜杠表示转义字符
spring.handlers
代码
- http\://www.xiu.com/schema/data=com.xiu.tag.XiuNameSpaceHandler
spring.schemas将告诉Spring配置文件知道,如果在配置中引用http://www.xiu.com/schema/data.xsd,它应该去什么地方找相应的xsd文件。
而spring.handlers文件将告诉Spring,应该使用哪个Handler注册扩展标签。
现在为止,一个完整的xml扩展标签全部完成,做一个小应用测试一下。
applicationContext.xml文件
<?xmlversion="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xiu="http://www.xiu.com/schema/data"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.xiu.com/schema/data
http://www.xiu.com/schema/data.xsd"> 红色的url表示要增加的
<xiu:DataSourceBean id="oneBean" url="99"/>
</beans>
测试类
package com.xiu.tag;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
public classMain {
public static void main(String[] args) {
ApplicationContext ctx = newClassPathXmlApplicationContext("applicationContext.xml");
DataSourceBean tag = (DataSourceBean)ctx.getBean("oneBean");
System.out.println("oneBean age is "+tag.getUrl());
System.out.println("oneBean age is "+tag.getDbname());
System.out.println("oneBean age is "+tag.getMaxIndex());
}
}
输出结果
oneBean age is 99
oneBean ageis orcl
oneBean ageis 100