9.1XML Schemas

附录的本部分列出了和核心容器相关的XML schemas。

9.1.1 util Schema

顾名思义,util标签处理常见的实用程序配置问题,例如配置集合,引用常量等。 要在util schema中使用标记,你需要在Spring XML配置文件的顶部有以下前导码(片段中的文本引用正确的模式,以便util命名空间中的标记可供你使用):

<?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 https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<!-- bean definitions here -->
</beans>

使用<util:constant/>

考虑如下的bean定义:

<bean id="..." class="...">
<property name="isolation">
<bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />
</property>
</bean>

上述配置使用Spring FactoryBean实现(FieldRetrievingFactoryBean)将bean上隔离属性的值设置为java.sql.Connection.TRANSACTION_SERIALIZABLE常量的值。 这一切都很好,但它很冗长,并且(不必要地)将Spring的内部管道暴露给最终用户。

以下基于XML Schema的版本更简洁,清楚地表达了开发人员的意图(“注入此常量值”),并且它可读性更好:

<bean id="..." class="...">
<property name="isolation">
<util:constant static-field="java.sql.Connection.TRANSACTION_SERIALIZABLE"/>
</property>
</bean>

使用字段值设置Bean属性或者构造函数参数

FieldRetrievingFactoryBean是一个FactoryBean,用于检索静态或非静态字段值。 它通常用于检索公共静态最终常量,然后可以使用它来为另一个bean设置属性值或构造函数参数。

以下示例显示了如何使用staticField属性公开静态字段:

<bean id="myField"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<property name="staticField" value="java.sql.Connection.TRANSACTION_SERIALIZABLE"/>
</bean>

还有一个便捷使用形式,其中静态字段被指定为bean名称,如以下示例所示:

<bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>

这确实意味着bean id不再有任何选择(因此引用它的任何其他bean也必须使用这个更长的名称),但这个表单定义非常简洁,非常方便用作内部 bean,因为不必为bean引用指定id,如下例所示:

<bean id="..." class="...">
<property name="isolation">
<bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />
</property>
</bean>

你还可以访问另一个bean的非静态(实例)字段,如FieldRetrievingFactoryBean类的API文档中所述。

在Spring中,将枚举值作为属性或构造函数参数注入bean中很容易。 实际上你不需要做任何事情或了解Spring内部的任何内容(甚至是关于诸如FieldRetrievingFactoryBean之类的类)。 以下示例枚举显示了注入枚举值的容易程度:

package javax.persistence;
public enum PersistenceContextType {
TRANSACTION,
EXTENDED
}

考虑如下PersistenceContextType的set方法和相应的bean定义:

package example;
public class Client {
private PersistenceContextType persistenceContextType;
public void setPersistenceContextType(PersistenceContextType type) {
this.persistenceContextType = type;
}
}
<bean class="example.Client">
<property name="persistenceContextType" value="TRANSACTION"/>
</bean>

使用Using <util:property-path/>

考虑如下例子:

<!-- target bean to be referenced by name -->
<bean id="testBean" class="org.springframework.beans.TestBean" scope="prototype">
<property name="age" value="10"/>
<property name="spouse">
<bean class="org.springframework.beans.TestBean">
<property name="age" value="11"/>
</bean>
</property>
</bean>
<!-- results in 10, which is the value of property 'age' of bean 'testBean' -->
<bean id="testBean.age" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>

上述配置使用Spring FactoryBean实现(PropertyPathFactoryBean)创建名为testBean.age的bean(类型为int),其值等于testBean bean的age属性。

现在考虑以下示例,它添加了一个<util:property-path />元素:

<!-- target bean to be referenced by name -->
<bean id="testBean" class="org.springframework.beans.TestBean" scope="prototype">
<property name="age" value="10"/>
<property name="spouse">
<bean class="org.springframework.beans.TestBean">
<property name="age" value="11"/>
</bean>
</property>
</bean>
<!-- results in 10, which is the value of property 'age' of bean 'testBean' -->
<util:property-path id="name" path="testBean.age"/>

<property-path />元素的path属性的值遵循beanName.beanProperty的形式。 在这种情况下,它会获取名为testBean的bean的age属性。 该age属性的值是10。

使用<util:property-path/>设置Bean属性或构造函数值

PropertyPathFactoryBean是一个FactoryBean,用于计算给定目标对象的属性路径。 目标对象可以直接指定,也可以通过bean名称指定。 然后,你可以在另一个bean定义中将此值用作属性值或构造函数参数。

以下示例按名称显示了针对另一个bean使用的路径:

// target bean to be referenced by name
<bean id="person" class="org.springframework.beans.TestBean" scope="prototype">
<property name="age" value="10"/>
<property name="spouse">
<bean class="org.springframework.beans.TestBean">
<property name="age" value="11"/>
</bean>
</property>
</bean>
// results in 11, which is the value of property 'spouse.age' of bean 'person'
<bean id="theAge"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetBeanName" value="person"/>
<property name="propertyPath" value="spouse.age"/>
</bean>

下面的例子中,path被用作内部bean:

<!-- results in 12, which is the value of property 'age' of the inner bean -->
<bean id="theAge"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetObject">
<bean class="org.springframework.beans.TestBean">
<property name="age" value="12"/>
</bean>
</property>
<property name="propertyPath" value="age"/>
</bean>

还有一个快捷方式表单,其中bean名称是属性路径。 以下示例显示了快捷方式:

<!-- results in 10, which is the value of property 'age' of bean 'person' -->
<bean id="person.age"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>

这个表单确实意味着bean的名称没有选择。 对它的任何引用也必须使用相同的id,即路径。 如果用作内部bean,则根本不需要引用它,如下例所示:

<bean id="..." class="...">
<property name="age">
<bean id="person.age"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>
</property>
</bean>

你可以在实际定义中专门设置结果类型。 对于大多数用例来说,这不是必需的,但它有时可能很有用。 有关此功能的更多信息,请参阅javadoc。

使用<util:properties/>

考虑下面的例子:

<!-- creates a java.util.Properties instance with values loaded from the supplied location -->
<bean id="jdbcConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:com/foo/jdbc-production.properties"/>
</bean>

上面的配置使用了FactoryBean实现(PropertiesFactoryBean)实例化了java.util.Properties,并从一个特定的Resource地址加载值。

以下示例使用util:properties元素来进行更简洁的表示:

<!-- creates a java.util.Properties instance with values loaded from the supplied location -->
<util:properties id="jdbcConfiguration" location="classpath:com/foo/jdbc-production.properties"/>

使用<util:list/>

考虑下面的例子:

<!-- creates a java.util.List instance with values loaded from the supplied 'sourceList' -->
<bean id="emails" class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
</list>
</property>
</bean>

前面的配置使用Spring FactoryBean实现(ListFactoryBean)来创建java.util.List实例,并使用从提供的sourceList获取的值对其进行初始化。

以下示例使用<util:list/>元素进行更简洁的表示:

<!-- creates a java.util.List instance with the supplied values -->
<util:list id="emails">
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
</util:list>

你还可以使用<util:list />元素上的list-class属性显式控制实例化和填充的List的确切类型。 例如,如果我们确实需要实例化java.util.LinkedList,我们可以使用以下配置:

<util:list id="emails" list-class="java.util.LinkedList">
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
<value>d'[email protected]</value>
</util:list>

如果没有 list-class ,容器会自己选择list实现。

使用<util:map/>

考虑下面的例子:

<!-- creates a java.util.Map instance with values loaded from the supplied 'sourceMap' -->
<bean id="emails" class="org.springframework.beans.factory.config.MapFactoryBean">
<property name="sourceMap">
<map>
<entry key="pechorin" value="[email protected]"/>
<entry key="raskolnikov" value="[email protected]"/>
<entry key="stavrogin" value="[email protected]"/>
<entry key="porfiry" value="[email protected]"/>
</map>
</property>
</bean>

上述配置使用Spring FactoryBean实现(MapFactoryBean)创建一个java.util.Map实例,该实例使用从提供的“sourceMap”获取的键值对进行初始化。

以下示例使用<util:map />元素进行更简洁的表示:

<!-- creates a java.util.Map instance with the supplied key-value pairs -->
<util:map id="emails">
<entry key="pechorin" value="[email protected]"/>
<entry key="raskolnikov" value="[email protected]"/>
<entry key="stavrogin" value="[email protected]"/>
<entry key="porfiry" value="[email protected]"/>
</util:map>

你还可以使用<util:map />元素上的'map-class'属性显式控制实例化和填充的Map的确切类型。 例如,如果我们确实需要实例化java.util.TreeMap,我们可以使用以下配置:

<util:map id="emails" map-class="java.util.TreeMap">
<entry key="pechorin" value="[email protected]"/>
<entry key="raskolnikov" value="[email protected]"/>
<entry key="stavrogin" value="[email protected]"/>
<entry key="porfiry" value="[email protected]"/>
</util:map>

如果未提供“map-class”属性,则容器将选择Map实现。

使用<util:set/>

考虑下面的例子:

<!-- creates a java.util.Set instance with values loaded from the supplied 'sourceSet' -->
<bean id="emails" class="org.springframework.beans.factory.config.SetFactoryBean">
<property name="sourceSet">
<set>
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
</set>
</property>
</bean>

上述配置使用Spring FactoryBean实现(SetFactoryBean)创建一个java.util.Set实例,该实例使用从提供的sourceSet获取的值进行初始化。

以下示例使用<util:set/>元素进行更简洁的表示:

<!-- creates a java.util.Set instance with the supplied values -->
<util:set id="emails">
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
</util:set>

你还可以使用<util:set/>元素上的set-class属性显式控制实例化和填充的Set的确切类型。 例如,如果我们确实需要实例化java.util.TreeSet,我们可以使用以下配置:

<util:set id="emails" set-class="java.util.TreeSet">
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
</util:set>

如果未提供set-class属性,则容器将选择Set实现。

9.1.2 aop Schema

aop标签用于配置Spring中的所有AOP,包括Spring自己的基于代理的AOP框架和Spring与AspectJ AOP框架的集成。 这些标签在题为“面向方面编程与Spring”的章节中进行了全面介绍。

为了完整性,要在aop模式中使用标记,你需要在Spring XML配置文件的顶部包含以下前导码(片段中的文本引用正确的模式,以便aop命名空间中的标记可以被你使用):

<?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 https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- bean definitions here -->
</beans>

9.1.3 context Schema

context标记处理与管道相关的ApplicationContext配置 - 也就是说,通常不是对最终用户很重要的bean,而是在Spring中执行大量“grunt”工作的bean,例如BeanfactoryPostProcessors。 以下代码段引用了正确的架构,以便你可以使用上下文命名空间中的元素:

<?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 https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- bean definitions here -->
</beans>

使用<property-placeholder/>

此元素激活$ {...}占位符的替换,这些占位符是针对指定的属性文件(作为Spring资源位置)解析的。 此元素是一种便捷机制,可为你设置PropertyPlaceholderConfigurer。 如果你需要更多地控制PropertyPlaceholderConfigurer,你可以自己明确定义一个。

使用<annotation-config/>

此元素激活Spring基础结构以检测bean类中的注解:

  • Spring的@Configuration模型

  • @Autowired / @Inject和@Value

  • JSR-250的@Resource,@PostConstruct和@PreDestroy(如果有的话)

  • JPA的@PersistenceContext和@PersistenceUnit(如果可用)

  • Spring的@EventListener

或者,你可以选择显式激活这些注解的各个BeanPostProcessors。

此元素不会激活Spring的@Transactional注解的处理; 你可以使用<tx:annotation-driven />元素来实现此目的。 同样,Spring的缓存注解也需要明确启用。

使用<component-scan/>

详细信息请参考:annotation-based container configuration.

使用<load-time-weaver/>

详细信息请参考:load-time weaving with AspectJ in the Spring Framework.

使用<spring-configured/>

详细信息请参考:using AspectJ to dependency inject domain objects with Spring.

使用<mbean-export/>

详细信息请参考: configuring annotation-based MBean export.

9.1.4 Beans Schema

最后但并非最不重要的是,我们在beans schema中有元素。自框架诞生以来,这些元素一直存在于Spring中。 这里没有显示bean schema中各种元素的示例,因为它们在依赖性和配置中得到了相当全面的介绍(实际上,在整个章节中)。

请注意,你可以向<bean/> XML定义添加零个或多个键值对。 如果有的话,使用这些额外的元数据完成的工作完全取决于你自己的自定义逻辑(因此,如果你按照标题为XML Schema Authoring的附录中所述编写自己的自定义元素,通常只会使用它。)

以下示例显示了周围<bean />上下文中的<meta />元素(请注意,没有任何逻辑可以解释它,元数据实际上是无用的)。

<?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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="foo" class="x.y.Foo">
<meta key="cacheName" value="foo"/>
<property name="name" value="Rick"/>
</bean>
</beans>

在前面的示例中,你可以假设有一些逻辑使用bean定义并设置一些使用提供的元数据的缓存基础结构。