A.2.XML Schema-based configuration
A.2. XML Schema-based configuration
A.2.1. Referencing the schemas
To switch over from the DTD-style to the new XML Schema-style, you need to make the following change.
<!-- DTD-style -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- <bean/>
definitions here -->
</beans>
The equivalent file in the XML Schema-style would be...
<!-- XML Schema-style -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- <bean/>
definitions here -->
</beans>
注意
The 'xsi:schemaLocation'
fragment is not actually required, but can be specified to refer to a local copy of a schema (which can be useful during development).
The above Spring XML configuration fragment is pretty much boilerplate; you can simply use this and continue to write <bean/>
definitions like you have always done. However, the entire point of switching over is to take advantage of the new Spring 2.0 XML tags since they make configuration easier. The section entitled 第 A.2.2 节 “The util
schema” demonstrates how you can start immediately by using some of the more common utility tags.
The rest of this chapter is devoted to showing examples of the new Spring XML Schema based configuration, with at least one example for every new tag. The format follows a before and after style, with a 'before'
snippet of XML showing the old (but still 100% legal and supported) style, followed immediately by an 'after'
example showing the equivalent in the new XML Schema-based style.
A.2.2. The util
schema
First up is coverage of the util
tags. As the name implies, the util
tags deal with common, utility configuration issues, such as configuring collections and suchlike.
To use the tags in the util
schema, you need to have the following preamble at the top of your Spring XML configuration file; the emboldened text in the snippet below references the correct schema so that the tags in the util
namespace are available to you.
<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- <bean/>
definitions here -->
</beans>
A.2.2.1. <util:constant/>
Before...
<bean id="..."> <property name="isolation"> <bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE" /> </property> </bean>
The above configuration uses a Spring FactoryBean
implementation, the FieldRetrievingFactoryBean
, to set the value of the 'isolation'
property on a bean to the value of the 'java.sql.Connection.TRANSACTION_SERIALIZABLE'
constant. This is all well and good, but it is a tad verbose and (unneccessarily) exposes Spring's internal plumbing to the end user.
The following XML Schema-based version is more concise and clearly expresses the developer's intent ('inject this constant value'), and it just reads better.
<bean id="..."> <property name="isolation"> <util:constant static-field="java.sql.Connection.TRANSACTION_SERIALIZABLE"/> </property> </bean>
A.2.2.1.1. Setting a bean property or constructor arg from a field value
FieldRetrievingFactoryBean
is a FactoryBean
which retrieves a static
or non-static field value. It is typically used for retrieving public
static
final
constants, which may then be used to set a property value or constructor arg for another bean.
Find below an example which shows how a static
field is exposed, by using the staticField
property:
<bean id="myField" > <property name="staticField"> <value>java.sql.Connection.TRANSACTION_SERIALIZABLE</value> </property> </bean>
There is also a convenience usage form where the static
field is specified as a bean name:
<bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE" />
This does mean that there is no longer any choice in what the bean id is (so any other bean that refers to it will also have to use this longer name), but this form is very concise to define, and very convenient to use as an inner bean since the id doesn't have to be specified for the bean reference:
<bean id="..."> <property name="isolation"> <bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE" /> </property> </bean>
It is also possible to access a non-static (instance) field of another bean, as described in the API documentation for the FieldRetrievingFactoryBean
class.
Injecting enum values into beans as either property or constructor arguments is a cinch in Spring, in that one doesn't actually have to do anything or know anything about the Spring internals (or even about classes such as the FieldRetrievingFactoryBean
). Let's look at an example to see how easy injecting an enum value is; consider this JDK 5 enum:
package javax.persistence; public enum PersistenceContextType { TRANSACTION, EXTENDED }
Now consider a setter of type PersistenceContextType
:
package example; public class Client { private PersistenceContextType persistenceContextType; public void setPersistenceContextType(PersistenceContextType type) { this.persistenceContextType = type; } }
.. and the corresponding bean definition:
<bean> <property name="persistenceContextType" value="TRANSACTION" /> </bean>
This works for classic type-safe emulated enums (on JDK 1.4 and JDK 1.3) as well; Spring will automatically attempt to match the string property value to a constant on the enum class.
A.2.2.2. <util:property-path/>
Before...
<!-- target bean to be referenced by name --> <bean id="testBean" singleton="false"> <property name="age" value="10"/> <property name="spouse"> <bean> <property name="age" value="11"/> </bean> </property> </bean> <!-- will result in 10, which is the value of property 'age' of bean 'testBean' --> <bean id="testBean.age"/>
The above configuration uses a Spring FactoryBean
implementation, the PropertyPathFactoryBean
, to create a bean (of type int
) called 'testBean.age'
that has a value equal to the 'age'
property of the 'testBean'
bean.
After...
<!-- target bean to be referenced by name --> <bean id="testBean" singleton="false"> <property name="age" value="10"/> <property name="spouse"> <bean> <property name="age" value="11"/> </bean> </property> </bean> <!-- will result in 10, which is the value of property 'age' of bean 'testBean' --> <util:property-path id="name" path="testBean.age"/>
The value of the 'path'
attribute of the <property-path/>
tag follows the form 'beanName.beanProperty'
.
A.2.2.2.1. Using <util:property-path/>
to set a bean property or constructor-argument
PropertyPathFactoryBean
is a FactoryBean
that evaluates a property path on a given target object. The target object can be specified directly or via a bean name. This value may then be used in another bean definition as a property value or constructor argument.
Here's an example where a path is used against another bean, by name:
// target bean to be referenced by name <bean id="person" singleton="false"> <property name="age"><value>10</value></property> <property name="spouse"> <bean> <property name="age"><value>11</value></property> </bean> </property> </bean> // will result in 11, which is the value of property 'spouse.age' of bean 'person' <bean id="theAge" > <property name="targetBeanName" value="person"/> <property name="propertyPath" value="spouse.age"/> </bean>
In this example, a path is evaluated against an inner bean:
<!-- will result in 12, which is the value of property 'age' of the inner bean --> <bean id="theAge" > <property name="targetObject"> <bean> <property name="age" value="12"/> </bean> </property> <property name="propertyPath"><value>age</value></property> </bean>
There is also a shortcut form, where the bean name is the property path.
<!-- will result in 10, which is the value of property 'age' of bean 'person' --> <bean id="person.age" />
This form does mean that there is no choice in the name of the bean, any reference to it will also have to use the same id, which is the path. Of course, if used as an inner bean, there is no need to refer to it at all:
<bean id="..."> <property name="age"> <bean id="person.age" /> </property> </bean>
The result type may be specifically set in the actual definition. This is not necessary for most use cases, but can be of use for some. Please see the Javadocs for more info on this feature.
A.2.2.3. <util:properties/>
Before...
<!-- creates a java.util.Properties
instance with values loaded from the supplied location -->
<bean id="jdbcConfiguration">
<property name="location" value="classpath:com/foo/jdbc-production.properties"/>
</bean>
The above configuration uses a Spring FactoryBean
implementation, the PropertiesFactoryBean
, to instantiate a java.util.Properties
instance with values loaded from the supplied Resource
location).
After...
<!-- creates a java.util.Properties
instance with values loaded from the supplied location -->
<util:properties id="jdbcConfiguration" location="classpath:com/foo/jdbc-production.properties"/>
A.2.2.4. <util:list/>
Before...
<!-- creates ajava.util.List
instance with values loaded from the supplied'sourceList'
--> <bean id="emails"> <property name="sourceList"> <list> <value>pechorin@hero.org</value> <value>raskolnikov@slums.org</value> <value>stavrogin@gov.org</value> <value>porfiry@gov.org</value> </list> </property> </bean>
The above configuration uses a Spring FactoryBean
implementation, the ListFactoryBean
, to create a java.util.List
instance initialized with values taken from the supplied 'sourceList'
.
After...
<!-- creates ajava.util.List
instance with values loaded from the supplied'sourceList'
--> <util:list id="emails"> <value>pechorin@hero.org</value> <value>raskolnikov@slums.org</value> <value>stavrogin@gov.org</value> <value>porfiry@gov.org</value> </util:list>
You can also explicitly control the exact type of List
that will be instantiated and populated via the use of the 'list-class'
attribute on the <util:list/>
element. For example, if we really need a java.util.LinkedList
to be instantiated, we could use the following configuration:
<util:list id="emails" list-class="java.util.LinkedList"> <value>jackshaftoe@vagabond.org</value> <value>eliza@thinkingmanscrumpet.org</value> <value>vanhoek@pirate.org</value> <value>d'Arcachon@nemesis.org</value> </util:list>
If no 'list-class'
attribute is supplied, a List
implementation will be chosen by the container.
Finally, you can also control the merging behavior using the 'merge'
attribute of the <util:list/>
element; collection merging is described in more detail in the section entitled 第 4.3.3.4.1 节 “集合合并”
A.2.2.5. <util:map/>
Before...
<!-- creates ajava.util.Map
instance with values loaded from the supplied'sourceMap'
--> <bean id="emails"> <property name="sourceMap"> <map> <entry key="pechorin" value="pechorin@hero.org"/> <entry key="raskolnikov" value="raskolnikov@slums.org"/> <entry key="stavrogin" value="stavrogin@gov.org"/> <entry key="porfiry" value="porfiry@gov.org"/> </list> </property> </bean>
The above configuration uses a Spring FactoryBean
implementation, the MapFactoryBean
, to create a java.util.Map
instance initialized with key-value pairs taken from the supplied 'sourceMap'
.
After...
<!-- creates ajava.util.Map
instance with values loaded from the supplied'sourceMap'
--> <util:map id="emails"> <entry key="pechorin" value="pechorin@hero.org"/> <entry key="raskolnikov" value="raskolnikov@slums.org"/> <entry key="stavrogin" value="stavrogin@gov.org"/> <entry key="porfiry" value="porfiry@gov.org"/> </util:map>
You can also explicitly control the exact type of Map
that will be instantiated and populated via the use of the 'map-class'
attribute on the <util:map/>
element. For example, if we really need a java.util.TreeMap
to be instantiated, we could use the following configuration:
<util:map id="emails" map-type="java.util.TreeMap"> <entry key="pechorin" value="pechorin@hero.org"/> <entry key="raskolnikov" value="raskolnikov@slums.org"/> <entry key="stavrogin" value="stavrogin@gov.org"/> <entry key="porfiry" value="porfiry@gov.org"/> </util:map>
If no 'map-class'
attribute is supplied, a Map
implementation will be chosen by the container.
Finally, you can also control the merging behavior using the 'merge'
attribute of the <util:map/>
element; collection merging is described in more detail in the section entitled 第 4.3.3.4.1 节 “集合合并”
A.2.2.6. <util:set/>
Before...
<!-- creates ajava.util.Set
instance with values loaded from the supplied'sourceSet'
--> <bean id="emails"> <property name="sourceSet"> <set> <value>pechorin@hero.org</value> <value>raskolnikov@slums.org</value> <value>stavrogin@gov.org</value> <value>porfiry@gov.org</value> </set> </property> </bean>
The above configuration uses a Spring FactoryBean
implementation, the SetFactoryBean
, to create a java.util.Set
instance initialized with values taken from the supplied 'sourceSet'
.
After...
<!-- creates ajava.util.Set
instance with values loaded from the supplied'sourceSet'
--> <util:set id="emails"> <value>pechorin@hero.org</value> <value>raskolnikov@slums.org</value> <value>stavrogin@gov.org</value> <value>porfiry@gov.org</value> </util:set>
You can also explicitly control the exact type of Set
that will be instantiated and populated via the use of the 'set-class'
attribute on the <util:set/>
element. For example, if we really need a java.util.TreeSet
to be instantiated, we could use the following configuration:
<util:set id="emails" set-class="java.util.TreeSet"> <value>pechorin@hero.org</value> <value>raskolnikov@slums.org</value> <value>stavrogin@gov.org</value> <value>porfiry@gov.org</value> </util:set>
If no 'set-class'
attribute is supplied, a Set
implementation will be chosen by the container.
Finally, you can also control the merging behavior using the 'merge'
attribute of the <util:set/>
element; collection merging is described in more detail in the section entitled 第 4.3.3.4.1 节 “集合合并”
A.2.3. The jee
schema
The jee
tags deal with JEE (Java Enterprise Edition)-related configuration issues, such as looking up a JNDI object and defining EJB references.
To use the tags in the jee
schema, you need to have the following preamble at the top of your Spring XML configuration file; the emboldened text in the following snippet references the correct schema so that the tags in the jee
namespace are available to you.
<?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.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">
<!-- <bean/>
definitions here -->
</beans>
A.2.3.1. <jee:jndi-lookup/>
(simple)
Before...
<bean id="simple"> <property name="jndiName" value="jdbc/MyDataSource"/> </bean>
After...
<jee:jndi-lookup id="simple" jndi-name="jdbc/MyDataSource"/>
A.2.3.2. <jee:jndi-lookup/>
(with JNDI environment setting)
Before...
<bean id="simple"> <property name="jndiName" value="jdbc/MyDataSource"/> <property name="jndiEnvironment"> <props> <prop key="foo">bar</prop> </props> </property> </bean>
After...
<jee:jndi-lookup id="simple" jndi-name="jdbc/MyDataSource"> <jee:environment>foo=bar</jee:environment> </jee:jndi-lookup>
A.2.3.3. <jee:jndi-lookup/>
(with JNDI environment settings)
Before...
<bean id="simple"> <property name="jndiName" value="jdbc/MyDataSource"/> <property name="jndiEnvironment"> <props> <prop key="foo">bar</prop> <prop key="ping">pong</prop> </props> </property> </bean>
After...
<jee:jndi-lookup id="simple" jndi-name="jdbc/MyDataSource">
<!-- newline-separated, key-value pairs for the environment (standard Properties
format) -->
<jee:environment>
foo=bar
ping=pong
</jee:environment>
</jee:jndi-lookup>
A.2.3.4. <jee:jndi-lookup/>
(complex)
Before...
<bean id="simple"> <property name="jndiName" value="jdbc/MyDataSource"/> <property name="cache" value="true"/> <property name="resourceRef" value="true"/> <property name="lookupOnStartup" value="false"/> <property name="expectedType" value="com.myapp.DefaultFoo"/> <property name="proxyInterface" value="com.myapp.Foo"/> </bean>
After...
<jee:jndi-lookup id="simple" jndi-name="jdbc/MyDataSource" cache="true" resource-ref="true" lookup-on-startup="false" expected-type="com.myapp.DefaultFoo" proxy-interface="com.myapp.Foo"/>
A.2.3.5. <jee:local-slsb/>
(simple)
The <jee:local-slsb/>
tag configures a reference to an EJB Stateless SessionBean.
Before...
<bean id="simple" > <property name="jndiName" value="ejb/RentalServiceBean"/> <property name="businessInterface" value="com.foo.service.RentalService"/> </bean>
After...
<jee:local-slsb id="simpleSlsb" jndi-name="ejb/RentalServiceBean" business-interface="com.foo.service.RentalService"/>
A.2.3.6. <jee:local-slsb/>
(complex)
<bean id="complexLocalEjb" > <property name="jndiName" value="ejb/RentalServiceBean"/> <property name="businessInterface" value="com.foo.service.RentalService"/> <property name="cacheHome" value="true"/> <property name="lookupHomeOnStartup" value="true"/> <property name="resourceRef" value="true"/> </bean>
After...
<jee:local-slsb id="complexLocalEjb" jndi-name="ejb/RentalServiceBean" business-interface="com.foo.service.RentalService" cache-home="true" lookup-home-on-startup="true" resource-ref="true">
A.2.3.7. <jee:remote-slsb/>
(simple)
The <jee:remote-slsb/>
tag configures a reference to a remote
EJB Stateless SessionBean.
Before...
<bean id="complexRemoteEjb" > <property name="jndiName" value="ejb/MyRemoteBean"/> <property name="businessInterface" value="com.foo.service.RentalService"/> <property name="cacheHome" value="true"/> <property name="lookupHomeOnStartup" value="true"/> <property name="resourceRef" value="true"/> <property name="homeInterface" value="com.foo.service.RentalService"/> <property name="refreshHomeOnConnectFailure" value="true"/> </bean>
After...
<jee:remote-slsb id="complexRemoteEjb" jndi-name="ejb/MyRemoteBean" business-interface="com.foo.service.RentalService" cache-home="true" lookup-home-on-startup="true" resource-ref="true" home-interface="com.foo.service.RentalService" refresh-home-on-connect-failure="true">
A.2.4. The lang
schema
The lang
tags deal with exposing objects that have been written in a dynamic language such as JRuby or Groovy as beans in the Spring container.
These tags (and the dynamic language support) are comprehensively covered in the chapter entitled 第 25 章 动态语言支持. Please do consult that chapter for full details on this support and the lang
tags themselves.
In the interest of completeness, to use the tags in the lang
schema, you need to have the following preamble at the top of your Spring XML configuration file; the emboldened text in the following snippet references the correct schema so that the tags in the lang
namespace are available to you.
<?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.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd">
<!-- <bean/>
definitions here -->
</beans>
A.2.5. The tx
(transaction) schema
The tx
tags deal with configuring all of those beans in Spring's comprehensive support for transactions. These tags are comprehensively covered in the chapter entitled 第 10 章 事务管理.
In the interest of completeness, to use the tags in the tx
schema, you need to have the following preamble at the top of your Spring XML configuration file; the emboldened text in the following snippet references the correct schema so that the tags in the tx
namespace are available to you.
<?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.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- <bean/>
definitions here -->
</beans>
注意
Often when using the tags in the tx
namespace you will also be using the tags from the aop
namespace (since the declarative transaction support in Spring is implemented using AOP). The above XML snippet contains the relevant lines needed to reference the aop
schema so that the tags in the aop
namespace are available to you.
A.2.6. The aop
schema
The aop
tags deal with configuring all things AOP in Spring: this includes Spring's own proxy-based AOP framework and Spring's integration with the AspectJ AOP framework. These tags are comprehensively covered in the chapter entitled 第 7 章 使用Spring进行面向切面编程(AOP).
In the interest of completeness, to use the tags in the aop
schema, you need to have the following preamble at the top of your Spring XML configuration file; the emboldened text in the following snippet references the correct schema so that the tags in the aop
namespace are available to you.
<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- <bean/>
definitions here -->
</beans>
A.2.7. The tool
schema
The tool
tags are for use when you want to add tooling-specific metadata to your custom configuration elements. This metadata can then be consumed by tools that are aware of this metadata, and the tools can then do pretty much whatever they want with it (validation, etc.).
The tool
tags are not documented in this release of Spring as they are currently undergoing review. If you are a third party tool vendor and you would like to contribute to this review process, then do mail the Spring mailing list. The currently supported tool
tags can be found in the file 'spring-tool.xsd'
in the 'src/org/springframework/beans/factory/xml'
directory of the Spring source distribution.