`
tom.duan
  • 浏览: 43052 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
文章分类
社区版块
存档分类
最新评论

Spring2.0 可扩展XML配置初探

阅读更多
Spring 2.0版本支持扩展XML配置,着实兴奋了一下,在我看来,Spring作为目前最流行的框架,不能扩展用户自定义的配置,实在是Spring的一个很不爽的地方,<bean />的方式用起来比较通用,起码到目前为止符合大部分人的使用习惯,并且能完成Spring所有的配置操作,但是对于第三方的提供商或则会经常扩展Spring功能的开发者来说,使用<bean />这样的配置方式或许不是他们最想要的,他们需要使组件的配置更加直观、易阅读、易扩展……试想使用下面的配置方式
<mytag:datasource id="datasource" 
       databaseType="oracle" 
       ip="192.168.1.110" 
       port="1521" 
       databaseName="myDB"
       userName="admin"
       password="password"
       />

<mytag:ehCache id="ehcache" 
       cache="true" 
       maxElements="100000" 
       timeToIdleSeconds="120" 
       timeToLiveSeconds="120"
       overflowToDisk="true"
       />

上面的代码中配置了两个组件,datasource和cache组件,相比普通的bean&propertiy方式,很显然,这种配置方式更直观,更易读,更重要的是,如果作为组件发布,使用者也可以很方便快捷的开始使用,而不需要关心组件的任何实现细节。

扩展XML配置大致需要一下几个步骤
1、创建一个需要扩展的组件
2、定义一个xsd文件描述组件内容
3、创建一个文件,实现BeanDefinitionParser接口,用来解析xsd文件中的定义和组件定义
4、创建一个Handler文件,扩展自NamespaceHandlerSupport,目的是将组件注册到Spring容器
5、编写spring.handlers和spring.schemas文件

提供一个简单的例子,来说明如何去扩展一个Spring配置,需求如下:使用自定义标签定义一个简单的bean,这个bean有一个或多个属性,标签定义完成后,可以在其他项目中用自定义标签来定义该bean。

首先,创建一个需要扩展的组件,在这里只是一个简单的bean,而且这个bean只有一个属性age.
One.java
package com.mysite.tag;

public class One {
	private String age;
	
	public One(){
		
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}
}


然后,建立一个xsd文件,来描述这个bean
mytag.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.mysite.org/schema/mytag"
		xmlns:xsd="http://www.w3.org/2001/XMLSchema"
		xmlns:beans="http://www.springframework.org/schema/beans"
		targetNamespace="http://www.mysite.org/schema/mytag"
		elementFormDefault="qualified"
		attributeFormDefault="unqualified">
	
	<xsd:import namespace="http://www.springframework.org/schema/beans"/>
	
	<xsd:element name="one">
		<xsd:complexType>
			<xsd:complexContent>
				<xsd:extension base="beans:identifiedType">
					<xsd:attribute name="age" type="xsd:string" default="99999"/>
				</xsd:extension>
			</xsd:complexContent>
		</xsd:complexType>
	</xsd:element>
</xsd:schema>

在上面的xsd文件描述了一个新的targetNamespace,并在这个空间中定义了一个name为one的element,one有一个age属性,类型为string,默认值为99999.xsd文件是xml DTD的替代者,使用XML Schema语言进行编写,这里对xsd schema不做太多解释,有兴趣可以参考相关的资料。

创建一个Java文件,该文件实现了BeanDefinitionParser接口,用来解析xsd文件中的定义并注册到组件中。
MyBeanDefinitionParser.java
package com.mysite.tag;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
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 MyBeanDefinitionParser implements BeanDefinitionParser{
	public BeanDefinition parse(Element arg0, ParserContext arg1) {
		RootBeanDefinition def = new RootBeanDefinition();
                //设置Bean Class
		def.setBeanClass(One.class);
		
                //注册ID属性
		String id = arg0.getAttribute("id");
		BeanDefinitionHolder idHolder= new BeanDefinitionHolder(def,id);
		BeanDefinitionReaderUtils.registerBeanDefinition(idHolder, arg1.getRegistry());
		
                //注册age属性
		String age = arg0.getAttribute("age");
		BeanDefinitionHolder ageHolder= new BeanDefinitionHolder(def,age);
		BeanDefinitionReaderUtils.registerBeanDefinition(ageHolder, arg1.getRegistry());
		def.getPropertyValues().addPropertyValue("age", age);
		
		return def;
	}
}


上面的代码仅仅实现了一个方法public BeanDefinition parse(Element arg0, ParserContext arg1),设置相关的Bean Class,解析了对应的xsd文件,并将解析的内容注册到上下文中,同时返回一个BeanDefinition对象(BeanDefinition是Spring的bean定义,提供了bean部分的操作方法,如isSingleton()、isLazyInit()等)。

注意,id属性是一个默认的属性,可以不在xsd文件中描述,但是需要注册它,否则将无法通过getBean方法获取标签定义的bean,也无法被其他bean引用。
另外,下面代码是给bean的属性赋值,这个是不可缺少的,否则在使用标签定义时将无法获取bean属性的值。
def.getPropertyValues().addPropertyValue("age", age);


然后为组件编写一个Handler文件,扩展自NamespaceHandlerSupport,它的作用是将组件注册到Spring容器
MyNameSpaceHandler.java
package com.mysite.tag;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

public class MyNameSpaceHandler extends NamespaceHandlerSupport {

	public void init() {
		 registerBeanDefinitionParser("one",new MyBeanDefinitionParser());
	}
}

实际执行的过程只有一句代码,注册了一个名字为one的扩展配置,包含了MyBeanDefinitionParser所parser相关xsd的内容。

到了这里,一个Spring扩展标签已经完成,但是我们目前还没办法使用它,Spring没那么聪明,它无法知道我们在什么地方定义了哪些扩展标签,这些标签将被谁解析,这个过程要我们通过一些文件来告知Spring知道,它们就是spring.handlers和spring.schemas,它们放在META-INF目录中,Spring.jar的META-INF目录中也有同名的文件,它们的文件内容基本上是相似的,而Spring在执行过程中,如果发现其他jar文件的META-INF文件夹中包含有这两个文件,Spring将会合并它们。
spring.schemas
http\://www.mysite.org/schema/mytag.xsd=com/mysite/tag/mytag.xsd


spring.handlers
http\://www.mysite.org/schema/mytag=com.mysite.tag.MyNameSpaceHandler


spring.schemas将告诉Spring配置文件知道,如果在配置中引用http://www.mysite.org/schema/mytag.xsd,它应该去什么地方找相应的xsd文件。
而spring.handlers文件将告诉Spring,应该使用哪个Handler注册扩展标签。

现在为止,一个完整的xml扩展标签全部完成,做一个小应用测试一下。
将整个项目打包成jar文件(别忘记META-INF内的两个文件),然后新建一个项目,引用刚才打包的jar文件,并引用Spring相关文件。
需要注意,自定义xml扩展配置只有xsd方式的引用才可以使用.
application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:tag="http://www.mysite.org/schema/mytag"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
	http://www.mysite.org/schema/mytag
	http://www.mysite.org/schema/mytag.xsd">

	<tag:one id="oneBean" age="99"/>
</beans>

在xml文件引用上可以看到,配置了一个名字为tag的名称空间,目标为http://www.mysite.org/schema/mytag命名空间,这个目标名称空间必须是存在于项目的引用中的(mytag.xsd中所定义的).
<tag:one id="oneBean" age="99"/>

上面定义了一个id为oneBean的组件,使用了“one”扩展标签,也就是我们在handler中所注册的,组件age属性的值为99。

Main.java
package com.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.mysite.tag.One;

public class Main {

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");
		One tag = (One) ctx.getBean("oneBean");
		System.out.println("oneBean age is "+tag.getAge());
	}
}

运行测试程序,结果如下
oneBean age is 99


Spring的xml扩展是一个非常有用的特性,在Spring2.0的版本中也提供了一些新的标签使用,如<aop>,<tx>等,但就目前来讲受大家关注程度并不高,我想大部分使用Spring的开发人员都在使用Spring开发企业应用,而Spring所提供的<bean />定义的方式对于开发人员来说已经能够满足需要,但是如果看的更远一些,在Spring以后的发展过程中,xml扩展应该会成为spring的核心特性之一,或许到时大家会习惯这样的方式来编写Spring配置文件吧
<XXCompany:XXXModule id="">
...
...

分享到:
评论
2 楼 tom.duan 2007-07-18  
楼上这么快,
p标签和<aop>、<tx>这些标签一样,是Spring2.0原本就提供的,而非自定义标签,本文的目的也只是说明自定义标签的定义及使用方法
1 楼 baallee 2007-07-18  
<?xml version="1.0" encoding="UTF-8"?> 
<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"    
xsi:schemaLocation="http://www.springframework.org/schema/beans  	   
http://www.springframework.org/schema/beans/spring-beans.xsd">  
<bean class="com.interface21.spring2.ioc.Person"     
p:name="Tony"    
p:age="53"     
p:house-ref="number10" />   
<bean class="com.interface21.spring2.ioc.House"     
id="number10"    
p:name="10 Downing Street"/>  
</beans>


对于简单的应用可以用p标签就好了。
自定意扩展应该用在更多的高级应用上

相关推荐

    spring2.0技术手册

    林信良著 spring2.0技术手册 《Spring 2.0技术手册》介绍了Spring 2.0的新特性,诸如Spring 2.0的新配置、新AOP支持、增强的IoC、JDBC和form标签等新功能。它通过实际完成一个完整的Spring项目示例,展示了与...

    Spring 2.0 spring 2.0 标准API

    Spring 2.0 标准API 用处不大的资源我不发

    Spring2.0jar包

    Spring2.0jar包,J2EE项目中,用于集成的框架。

    Spring 2.0 中文参考手册

    Spring 2.0 中文参考手册,Spring 2.0 中文参考手册,Spring 2.0 中文参考手册,Spring 2.0 中文参考手册Spring 2.0 中文参考手册,

    Spring2.0技术手册(林信良)_part2

    本书介绍了Spring 2.0的新特性,诸如Spring 2.0的新配置、新AOP支持、增强的IoC、JDBC和form标签等新功能。它通过实际完成一个完整的Spring项目示例,展示了与Spring相关API的使用技巧,能够显著减少每一位入门者...

    Spring2.0技术手册

    本书介绍了Spring 2.0的新特性,诸如Spring 2.0的新配置、新AOP支持、增强的IoC、JDBC和form标签等新功能。它通过实际完成一个完整的Spring项目示例,展示了与Spring相关API的使用技巧,能够显著减少每一位入门者...

    详尽的Spring2.0学习提纲

    对于学习Spring2.0很好的指导作用,给初学者指明一个学习的方向和思路。

    spring2.0jar包(一)

    spring2.0jar包(一) spring2.0jar包(一) spring2.0jar包(一) spring2.0jar包(一) spring2.0jar包(一) spring2.0jar包(一) spring2.0jar包(一)

    SPRING2.0开发详解

    SPRING2.0开发详解: 详细阐述了SPRING2.0的核心技术和框架整合能力

    spring2.0 中文帮助文档 pdf

    spring2.0 中文帮助文档 spring2.0 中文帮助文档 spring2.0 中文帮助文档 spring2.0 中文帮助文档 spring2.0 中文帮助文档

    spring2.0 使用 Quartz 必备包

    spring2.0 使用 Quartz 必备包 里面有: quartz-all-1.5.2.jar spring-support.jar 适合:SSH框架 spring2.0 strut2.0 hibernate3.2等

    Spring2.0中文教程

    Spring2.0中文教程

    spring2.0(中文)

    本书介绍了Spring2.0的新特性,诸如Spring2.0的新配置、新AOP支持、增强的IOC、JDBC和form标签等新功能。它通过实际完成一个完整的Spring项目示例,展示了与Spring相关API的使用技巧,能够显著减少每一位入门者摸索...

    spring2.0技术手册 (扫描版)

    第1章认识Spring 第2章Spring入门 第3章Bean、消息、事件 第4章SpringAOP 第5章JDBC、事务支持 第6章Hibernate与Spring 第7章SpringWebMVC框架 第8章View层方案、Web框架整合 第9章API封装 第10章项目:...

    spring2.0中文手册及使用指南 chm

    spring2.0中文手册及使用指南,chm格式

    spring2.0中文文档

    spring2.0中文文档

    Spring2.0宝典源代码

    Spring2.0宝典全书源代码,作者李刚,随书所附的光盘

    Spring2.0的配置

    看着有用就自己下载吧

    SPRING2.0中文文档

    全中文的SPRING2.0技术文档。

    spring2.0学习源码

    spring2.0宝典源代码

Global site tag (gtag.js) - Google Analytics