`
hypgr
  • 浏览: 273372 次
社区版块
存档分类
最新评论

Spring Schemas and Namespaces

阅读更多

 

本章研究Spring命名空间,你将学到新的并且更简单的办法创建Spring bean XML file,并且我们将讨论所有Spring框架提供的schema。此外,你还将看到如何创建自定义Spring schema和他的处理器。

新的schema最主要的吸引力是他们使用命名空间样式的配置文件,这样他们将更加简单明了并且有更丰富的表达力。他们允许你非常准确的了解每一个元素和属性允许的值。因为你可以创建自己的scheam和命名空间,所以你可以使配置文件写起来非常简单。最普通的事情是你有一个共享组件具有他的自定义 Spring配置schema和parser,比如说在你们公司的Maven2仓库中。其他的开发者可以使用这个共享组件而不需要花费很多时间去阅读说明文档。你也可以明显的减少丢失配置的情况。

Why the New Configuration?

在使用Spring 1.x时,我们使用非常复杂的XML文件去描述bean的配置信息和依赖关系。我们可以在Spring 2.5中继续这么做,不过现在我们可以获得一些标准XSD schema和scheam handler带来的好处。

考虑就样式的配置文件(如下):他对于老练的Spring 1.x开发这来说是非常易读的,但是仍然非常冗长。

Description: Very Verbose Spring 1.x-Style Context File

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
	"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<bean id="transactionManager"
		class="com.apress.prospring2.namespaces.NoopPlatformTransactionManager"/>
	<bean id="greetingsList"
		class="org.springframework.beans.factory.config.ListFactoryBean">
		<property name="sourceList">
			<list>
				<value>Hello, World</value>
				<value>What do you want to do tomorrow?</value>
				<value>Nazdar, prdi</value>
			</list>
		</property>
	</bean>
	<bean id="greeterService"
		class="org.springframework.transaction.interceptor.
			TransactionProxyFactoryBean">
		<property name="transactionManager" ref="transactionManager"/>
		<property name="target">
			<bean class="com.apress.prospring2.namespaces.ComplexGreeterService">
				<property name="greetings" ref="greetingsList"/>
			</bean>
		</property>
		<property name="transactionAttributes">
			<props>
				<prop key="greet*">PROPAGATION_REQUIRED</prop>
			</props>
		</property>
	</bean>
</beans>
 

一个Spring 2.5样式的配置文件并不一定非常短小精悍,但是他更加清楚并且更容易理解。下面是新样式的配置文件,

Descrption: The Configuration File from Listing 7-1 in Spring 2.5

<?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:util="http://www.springframework.org/schema/util"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/util
		http://www.springframework.org/schema/util/spring-util-2.5.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
	<bean id="transactionManager"
		class="com.apress.prospring2.namespaces.NoopPlatformTransactionManager" />
	<util:list id="greetingsList">
		<value>Hello, world</value>
		<value>What do you want to do tomorrow?</value>
		<value>Nazdar, prdi</value>
	</util:list>
	<bean id="greeterService" class="com.apress.prospring2.namespaces.ComplexGreeterService">
		<property name="greetings" ref="greetingsList" />
	</bean>
	<tx:advice id="greeterServiceAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="greet*" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>
	<aop:config>
		<aop:pointcut id="greeterServiceOperation"
			expression="execution(* com.apress.*.*.GreeterService.*(..))" />
		<aop:advisor advice-ref="greeterServiceAdvice"
			pointcut-ref="greeterServiceOperation" />
	</aop:config>
</beans>

 

 

 

正如你看到的一样,新的配置文件并不是必须短小精悍,即使XML scheam定义的内容非常多。新代码主要的优势是非常清楚并且容易理解:greeterService不在像target bean一样隐藏在TransactionProxyFactoryBean中。除此之外使用指定的XSD schema还可以使很多IDE获得代码提示功能,你可以使用code completion获得可能的值或者其他功能。

Schemas Included in Spring 2.5

下面让我们看一下Spring框架支持的不同schema。下边总结了可用的schema和他们的用途,

Description: Schemas Included in the Spring 2.5 Distribution

Schema Usage
util Utility functions for declaration of constants,lists,maps,properties,and property paths.
j2ee J2EE functions for working with the JNDI and EJBs.
jms Adds support for simple configuration of JMS beans.
lang Allows objects exposed by languages such as JRuby to be used as Spring beans.
tx Allows you to declare transactional properties of your Spring beans
aop Deals with aspect-oriended programming elements,such as pointcuts and advice
tool This schema is intended to be used by developers of additional components;the developers use the tool schema to add metadata that the third-party components use。
context Allows you to control the wiring up process and bean post-processing
beans Use this schema to declare beans,aliases,and imports;this is usually the default schema in the XML file.

除了上面的这些,Spring文件夹还提供了很多其他的,比如Spring Security,和其他第三方提供的,比如Oracle Coherence就有他们的自定义namespace。下面我们将讨论每一个上表列出的schema

The beans Schema

我们从这些schema中最重要的beans schema开始。他与Spring框架中最早出现的标签相同。在某个XML文件中指定这个schema为默认的schema只需要在XML文件中简单的生命他,如,

Description: beans Schema Example

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
	<!-- bean declarations here -->
</beans>
 

上面的代码非常简单,并没有引用beans schema中的元素。beans scheam包含四个元素:bean,alias,import和description。bean元素匹配Spring DTD中定义bean的元素。在本书第三章和第四章中对此有详细的描述。

The context Schema

Spring 2.5引入了context schema。这是排名第二的基础scheam,虽然在大多数应用程序中你都不会使用他。他修改Spring的bean创建进程的核心行为。下面清单显示了如何在Spring context files中配置property placeholders。

Description: Beans for the Property Placeholder Configuration

<?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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-2.5.xsd">
	<bean id="test" class="com.apress.prospring2.ch07.context.TestBean">
		<property name="name" value="${name}"/>
	</bean>
	<context:property-placeholder location=
		"classpath:/com/apress/prospring2/ch07/context/test.properties" />
</beans>
 

上面的代码显示了如何使用context schema配置property placeholder。他可能使用一个位置(location)或使用逗号分隔的多个位置的列表配置property placeholder。如果无法找到你要使用的property,property placeholder将以Java System properties为标准进行检查。

The util Schema

It contains definitions that are shorthand for the old factory beans.

Description: Usage of the util Schema

 
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLschema-instance"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/util
		http://www.springframework.org/schema/util/spring-util-2.5.xsd">
	<!-- bean declarations here -->
</beans>
 
 
下面让我们看一下util schema中的若干元素,从最简单的util:constant开始,

Description: Constant Declaration

 
<util:constant id="X" static-field="java.lang.Integer.MAX_VALUE"/>

上面的代码声明了一个DI为X的bean,并设置它的值为Integer.MAX_VALUE。

The next element,util:list,声明一个实现了java.util.List的bean,更准确的说是java.util.List。你可以知道List的实现类并且向List中添加值,

Description: Declaration of the list Bean

<util:constant id="Y" static-field="java.lang.Integer.MAX_VALUE"/>

<util:list id="X" list-class="java.util.ArrayList">
	<value>value1</value>
	<ref bean="Y"/>
</util:list>

 

上面的代码声明了ID为X的,类型为java.util.ArrayList<Object>的bean。并设置他的值为 String(“value1″)和Integer.MAX_VALUE。我们通过下面的Java代码验证这个bean,

Descrpiton: Usage of the util:list Declaration

List y = (List)context.getBean("X");
for (Object o : y) {
	System.out.println(o.getClass() + " " + o);
}

运行结果:

class java.lang.String value1
class java.lang.Integer 2147483647

  

接着我们看一下util:map元素。你可以指定一个实现java.util.Map接口的类的bean,并设置map的元素。如,

Description: Usage of the map Declaration

<util:constant id="Y" static-field="java.lang.Integer.MAX_VALUE"/>

<util:map id="Z" map-class="java.util.HashMap">
	<entry key="x" value="y"/>
	<entry key="y"><ref bean="X"/></entry>
</util:map>

 这里声明了一个bean ID为Z并且实现java.lang.Map<Object,Object>接口的,类型为java.util.HashMap的bean。他的值为”x” => String(“y”)和”y” => Integer.MAX_VALUE。用类似上面的JAVA代码验证结果如下,

y => class java.lang.Integer 2147483647
x => class java.lang.String y"

 

下面是util schema中的util:properties元素,

Description: Declaration of the properties Element

<util:properties id="BeanId"
	location="classpath:com/apress/prospring2/ch07/util/Main.properties"/>

 

被BeanId表示的bean声明为java.util.Properties bean并且从classpath中的com/apress/prospring2/ch07/util/Main.properties中读取值。就像你看到的一样,location属性可以是一个Spring resource,这意味着你可以为location属性设置任何经过Spring resource editor验证过的pattern。

下一个元素是util:property-path元素。它允许从一个存在的bean中提取属性值。考虑下面清单,我们有一个ID为simple的 SimpleBean类型的bean。我们将通过util:property-path使用simple.getName()返回的值创建一个ID为Q的 bean。

Description: Declaration of the simple and property-path Beans

// SimpleBean.java
public class SimpleBean {

	private String name;
	private String value;

	public SimpleBean() {
		this.name = "Name";
		this.value = "Anirvan Chakraborty";
	}

	public String getName() {
		return name;
	}

	public String getValue() {
		return value;
	}
}

 Description: greeter-context-2.0.xml

<bean id="simple" class="com.apress.prospring2.namespaces.util.SimpleBean"/>
<util:property-path id="Q" path="simple.name"/>

 

这里ID为Q的util:property-path bean将被设置为“Name”。

最后,util:set元素声明实现了java.util.Set<Object>接口。

Description: Showing a util:set Configuration

<util:constant id="X" static-field="java.lang.Integer.MAX_VALUE"/>

<util:set id="S" set-class="java.util.HashSet">
	<value>foo</value>
	<ref bean="X"/>
</util:set>

 

set元素必须符合指定的Set实现类的规范(contract);也就是说如果我们改变set-class为 java.util.TreeSet,上面构造的bean将会失败,因为TreeSet不能包含不同类型的对象。

The tx Schema

Spring提供了广泛的事务支持,<tx>标签将用来配置事务bean。下面的代码片段引用了正确的schema并使你可以使用tx 命名空间中的标签。

Description: Code Snippet for Transactional Bean Declaration Using the tx Namespace

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLschema-instance"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
		http://www.springframework.org/schema/util
		http://www.springframework.org/schema/util/spring-util-2.0.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

	<!—transactional bean declarations here -->

</beans>

 

后面有一章(第16章)会专门讨论Spring对事务的支持,同样会讨论<tx>标签的各种属性。

The aop Schema

<aop>标签配置和AOP有关的Spring bean,包括Spring自己的proxy基础的AOP框架和Spring整合的AspectJ AOP框架。这些标签在前面的章节有介绍。所以这里只简单的说一下,

Description: Correct Usage of the aop Schema

<?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:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
	<!-- <bean/> definitions here -->
</beans>

 

The jee Schema

Spring通过使用jee命名空间提供对Java Enterprise Edition(Java EE或JEE)的支持。他现在可以通过简单的方法配置通过JNDI查找对象。如,

Description: Configuration for Correct Usage of the jee Namespace

<?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:jee="http://www.springframework.org/schema/jee"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/jee
		http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">
	<!-- <bean/> definitions here -->
</beans>

 

为了比对新旧配置文件,下面我们来看一下在Spring 1.x中的JNDI对象查找配置,

Description: Spring 1.x-Specific Configuration of JNDI Object Lookup

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
	<property name="jndiName" value="jdbc/dataSource"/>
</bean>
<bean id="someDao" class="com.apress.chapter7.JdbcSomeDao">
	<property name="dataSource" ref="dataSource"/>
</bean>

 

上面你可以看到江jndiObjectFactoryBean配置为简单的Spring bean,并将这个bean的引用传递给Spring数据访问对象bean。

下面让我们看一下使用Spring 2.5的jee命名空间进行更简单的配置。

Description: JNDI Object Lookup Using the <jee> Tag

<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyDataSource"/>
<bean id="userDao" class="com.foo.JdbcUserDao">
	<property name="dataSource" ref="dataSource"/>
</bean>

 

The lang Schema

lang schema涉及关于在Spring容器中使用动态语言(如,JRuby或Groovy)暴露对象的领域。这里的标签(和动态语言)将在这本书的14章讨论。

Description: Correct Usage of the lang Schema

<?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:lang="http://www.springframework.org/schema/lang"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans ➥
		http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/lang ➥
		http://www.springframework.org/schema/lang/spring-lang-2.5.xsd">
<!-- <bean/> definitions here -->
</beans>

 

Note 我们忽略了Spring 2.5的tool schema,他现在正在被重新审核。不过你可以通过spring-tool-2.5.xsd对他进行学习。

Behind the Schema Scenes

现在了解了如何使用标准的schema,下面讲学习更有趣的东西-Spring如何处理新的配置文件。下面让我们看一下当Spring遭遇一个 schema引用时发什么事情。

下图是一个UML sequence diagram。他显示了Spring如何读取配置文件和处理步骤。

Description: Loading Spring configuration

一个非常好的开始的地方是创建ApplicationContext的实现时,例如调用new ClasspathXmlApplicationContext()。如果我们使用默认设置,Spring将在 AbstractXmlApplicationContext中使用XmlBeanDefinitionReader类读取bean定义,在处理过程中实际使用DefaultBeanDefinitionDocumentReader.

DefaultBeanDefinitionDocumentReader创建BeanDefinitionParserDeletgate,它用来处理DefaultBeanfinitionDocumentReader遭遇到的XML事件。 BeanDefinitionParserDelegate使用DefaultNamespaceHandlerResolver获得与指定的 namespaceUri相符合的NamespaceHandlerResolver。

DefaultNamespaceHandlerResolver使用META-INF/spring.handles文件决定符合给定的 namespace URI的NamespaceHandler接口实现。像XmlBeanDefinitionReader读取XML配置文件一样,它为每一个遭遇的他的命名空间的元素调用NamespaceHandler实现。一旦元素被读取,BeanDefinitions调用BeanDefinition或者更新 BeanDefinitionHolder实例。BeanDefinition用来实例化被配置的bean。下面是默认的/META-INF /spring.handlers

Description: Default META-INF/spring.handlers File

http\://www.springframework.org/schema/util=
	org.springframework.beans.factory.xml.UtilNamespaceHandler
http\://www.springframework.org/schema/aop=
	org.springframework.aop.config.AopNamespaceHandler
http\://www.springframework.org/schema/lang=
	org.springframework.scripting.config.LangNamespaceHandler
http\://www.springframework.org/schema/tx=
	org.springframework.transaction.config.TxNamespaceHandler
http\://www.springframework.org/schema/jee=
	org.springframework.ejb.config.JeeNamespaceHandler
http\://www.springframework.org/schema/p=
	org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler

 

这是一个简单的properties样式的文件,这里的key是命名空间URI,value是与命名空间对应的实现了 NamespaceHandler接口的类。实际上大部分实现都不是直接实现这个接口的,而是扩展自NamespaceHandlerSupport便捷类。

NamespaceHandlerSupport类允许你非常容易的实现NamespaceHandler并且允许你通过注册一个 BeanDefinitionParser去处理自定义schema的不同元素。一般会在init()方法中注册 BeanDefinitionParser(通常是一个静态嵌套类)。

Description: Typical Implementation of a Class that Extends NamespaceHandlerSupport

public class CustomNamespaceHandler extends NamespaceHandlerSupport {

	private static class GreeterBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
		protected Class getBeanClass(Element element) {
			return GreeterFactoryBean.class;
		}
		protected void doParse(Element element,ParserContext parserContext, BeanDefinitionBuilder builder) {
			// implementation of the doParse method.
		}
		public void init() {
			registerBeanDefinitionParser("greeter", new GreeterBeanDefinitionParser());
		}
	}
}

 

Custom Schemas

现在你知道Spring如何处理配置文件的读取,你可以容易的创建自定义schema和合适的NamespaceHandler。下面书上显示的是这个例子的目录结构。懒得弄图了。

这个例子有九个文件:一个简单的Greeter接口和他的实现StdoutGreeter。一个Main类完成test,它使用 ClasspathXmlApplicationContext读取custom-context.xml文件。从命名空间处理这一点来看,最重要的文件是spring.handlers,spring.schemas,custom.xsd,GreeterFactoryBean和 CustomNamespaceHandler。让我们通过下面清单开始分析这个简单的例子,

Description: The custom.xsd Schema File

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://prospring2.apress.com/namespaces/custom"
	xmlns:xsd="http://www.w3.org/2001/XMLschema"
	targetNamespace="http://com.apress.prospring2/ch07/custom"
	elementFormDefault="qualified">
	<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
	<xsd:element name="greeter">
		<xsd:annotation>
			<xsd:documentation>...</xsd:documentation>
		</xsd:annotation>
		<xsd:complexType>
			<xsd:attribute name="id" type="xsd:ID"/>
			<xsd:attribute name="count" type="xsd:integer" use="required">
				<xsd:annotation>
					<xsd:documentation>...</xsd:documentation>
				</xsd:annotation>
			</xsd:attribute>
			<xsd:attribute name="message" type="xsd:string" use="required">
				<xsd:annotation>
					<xsd:documentation>...</xsd:documentation>
				</xsd:annotation>
			</xsd:attribute>
		</xsd:complexType>
	</xsd:element>
</xsd:schema>

 

这里我们定义了一个元素,greeter,他有三个必须的属性。id属性的类型是xsd:ID,count的类型是 xsd:integer,message的类型是xsd:string。通过严格的指定每个属性允许的类型,我们可以强迫任何使用我们的组件的开发者使用正确的数据类型。

注意schema loction是http://com.apress.prospring2/ch07/custom;这是一个URI,在程序运行是他可能无法访问。这就是为什么我们需要创建META-INF/spring.schemas文件,这个文件指定了URI相应的classpath位置,

Description: The spring.schemas File

http\://com.apress.prospring2/ch07/custom =\
	/com/apress/prospring2/ch07/custom/custom.xsd

 

注意这个properties样式的文件中的key匹配schema的URI,value匹配custom.xsd文件在classpath中的位置。下面我们注册一个可以处理http://com.apress.prospring2/ch07/custom中的元素的 NamespaceHandler实现。我们用META-INF/spring.handlers文件做这件事情,

Description: The spring.handlers File

http\://com.apress.prospring2/ch07/custom =\
com.apress.prospring2.namespaces.custom.CustomNamespaceHandler

 

这个文件告诉Spring读取CustomNamespaceHandler并使用它处理custom schema中的元素。

在我们创建NamespaceHandler实现之前,我们必须创建GreeterFacotryBean。这是一个标准的Spring FactoryBean实现,用来根据配置创建合适的Greeter接口的实现的实例。

Description: Implementation of the GreeterFactoryBean

public class GreeterFactoryBean extends AbstractFactoryBean {

	private String message;
	private int count;

	public void setMessage(String message) {
		this.message = message;
	}

	public void setCount(int count) {
		this.count = count;
	}

	protected Object createInstance() {
		if (this.message == null) {
			throw new IllegalArgumentException("'message' is required");
		}
		return new StdoutGreeter(this.count, this.message);
	}

	public Class getObjectType() {
		return Greeter.class;
	}

}

 

这个实现没有什么不好理解的地方:createInstance()方法使用message和count创建StdoutGreeter的实例,StdoutGreeter实现了Greeter接口。我们在CustomNamespaceHandler中使用这个bean factory。

Description: CustomNamespaceHandler Implementation

public class CustomNamespaceHandler extends NamespaceHandlerSupport {

	private static class GreeterBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
		protected Class getBeanClass(Element element) {
			return GreeterFactoryBean.class;
		}

		protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
			builder.addPropertyValue("message", element.getAttribute("message"));
			String countString = element.getAttribute("count");
			try {
				int count = Integer.parseInt(countString);
				builder.addPropertyValue("count", count);
			} catch (NumberFormatException ex) {
				throw new RuntimeException(ex);
			}
		}
	}

	public void init() {
		registerBeanDefinitionParser("greeter", new GreeterBeanDefinitionParser());
	}
}

 

这个文件中有几个关键的地方。第一个地方是扩展子帮助类NamespaceHandlerSupport。所以我们只需要实现init()方法,在这里我们为所有的custom:greeter元素注册解析器;所有我们需要做的事情就是实现getBeanClass()方法和doParse()方法。Spring将创建getBeanClass()方法返回的类的实例并为所有在doParse()方法中调用 builder.addPropertyValue()添加的属性调用setter方法。在这个例子中,调用的方法是 GreeterFactoryBean.setMessage()和GreeterFactoryBean.setCount()。这同样是我们在 doParse()方法中完成的。我们知道这些属性的存在,因为schema验证进程决定他们必须存在。我们同样知道count的值是整形,但是我们只能从String中进行解析,因为element.getAttribute()方法返回String。因此,catch块永远不会被执行。

最后的问题是custom-context.xml和他的测试程序,

Description: The custom-context.xml File

<?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:custom="http://prospring2.apress.com/namespaces/custom"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://prospring2.apress.com/namespaces/custom
		http://prospring2.apress.com/namespaces/custom.xsd">

	<custom:greeter id="greeter" count="10" message="goo"/>

</beans>

 

这里我们有一个非常整洁的属性定义。

Description: Code Fragment Showing Usage of the Custom Namespace Handler

// code fragment of Main.java
ApplicationContext context =
	new ClassPathXmlApplicationContext("classpath*:**/custom-context.xml");
Greeter greeter = (Greeter)context.getBean("greeter");
greeter.greet();

 

IDE Configuration

略…

Summary

In this chapter, you have seen how Spring 2.5 handles the new XML context files. Like previous releases of the Spring Framework, Spring 2.5 is fully backward compatible, so all your existing Spring 1.x document-type-definition–based (DTD-based) configuration will still work. But even though you can still use Spring 1.x DTD context files, you will get much more flexibility from using the new schema-based context files. In fact, some Spring 2.5 features are quite verbose to configure using the standard DTD-based approach. Good examples of this are the configuration of AspectJ beans and dynamic languages (for more information about AspectJ and Spring, see Chapter 6; for dynamic languages, see Chapter 14).

As well as understanding the standard namespaces provided by Spring, you now know how to create your own custom namespace. This is particularly helpful if you are developing a component of an application that many developers of your organization are going to use. If you write a custom namespace for its configuration, you can ensure that the beans will not be misconfigured.

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics