XML Schema

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

util Schema

顾名思义,util 标签用于处理常见的、工具性质的配置问题,例如配置集合、引用常量等。要使用 util Schema 中的标签,您需要在 Spring XML 配置文件顶部添加以下序言(代码段中的文本引用了正确的 Schema,以便 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 的 isolation 属性值设置为 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,用于检索静态或非静态字段值。它通常用于检索 public static final 常量,然后这些常量可用于设置另一个 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 等类)。以下枚举示例展示了注入枚举值有多简单

  • Java

  • Kotlin

package jakarta.persistence;

public enum PersistenceContextType {

	TRANSACTION,
	EXTENDED
}
package jakarta.persistence

enum class PersistenceContextType {

	TRANSACTION,
	EXTENDED
}

现在考虑以下 PersistenceContextType 类型的 setter 方法以及相应的 Bean 定义

  • Java

  • Kotlin

package example;

public class Client {

	private PersistenceContextType persistenceContextType;

	public void setPersistenceContextType(PersistenceContextType type) {
		this.persistenceContextType = type;
	}
}
package example

class Client {

	lateinit var persistenceContextType: PersistenceContextType
}
<bean class="example.Client">
	<property name="persistenceContextType" value="TRANSACTION"/>
</bean>

使用 <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>

在以下示例中,路径针对内部 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>

上述配置使用 Spring FactoryBean 实现(即 PropertiesFactoryBean)实例化一个 java.util.Properties 实例,其值从提供的 资源 位置加载)。

以下示例使用 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 实现。

aop Schema

aop 标签用于配置 Spring 中的所有 AOP 相关内容,包括 Spring 自身的基于代理的 AOP 框架以及 Spring 与 AspectJ AOP 框架的集成。这些标签已在题为“使用 Spring 进行面向切面编程”的章节中进行了全面介绍。

为了完整起见,要使用 aop Schema 中的标签,您需要在 Spring XML 配置文件顶部添加以下序言(代码段中的文本引用了正确的 Schema,以便 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>

context Schema

context 标签用于处理与“底层实现”相关的 ApplicationContext 配置——也就是说,它们通常不是对最终用户很重要的 Bean,而是执行 Spring 中许多“繁重”工作的 Bean,例如 BeanfactoryPostProcessors。以下代码段引用了正确的 Schema,以便 context 命名空间中的元素对您可用

<?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 资源位置)进行解析。此元素是一种便利机制,它为您设置了一个 PropertySourcesPlaceholderConfigurer。如果您需要更精细地控制特定的 PropertySourcesPlaceholderConfigurer 设置,可以自己明确将其定义为一个 Bean。

对于给定的应用,应该只定义一个这样的元素,包含其所需的属性。只要有不同的占位符语法 (${…​}),就可以配置多个属性占位符。

如果您需要模块化用于替换的属性来源,则不应创建多个属性占位符。相反,每个模块应该向 Environment 贡献一个 PropertySource。或者,您可以创建自己的 PropertySourcesPlaceholderConfigurer Bean 来收集要使用的属性。

使用 <annotation-config/>

此元素激活 Spring 基础设施以检测 Bean 类中的注解

  • Spring 的 @Configuration 模型

  • @Autowired/@Inject@Value@Lookup

  • JSR-250 的 @Resource@PostConstruct@PreDestroy(如果可用)

  • JAX-WS 的 @WebServiceRef 和 EJB 3 的 @EJB(如果可用)

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

  • Spring 的 @EventListener

或者,您可以选择明确激活这些注解对应的各个 BeanPostProcessors

此元素不激活 Spring 的 @Transactional 注解的处理;为此目的,您可以使用 <tx:annotation-driven/> 元素。类似地,Spring 的缓存注解也需要明确启用

使用 <component-scan/>

此元素在基于注解的容器配置一节中有详细介绍。

使用 <load-time-weaver/>

此元素在Spring Framework 中使用 AspectJ 进行加载时织入一节中有详细介绍。

使用 <spring-configured/>

此元素在使用 AspectJ 通过 Spring 进行领域对象依赖注入一节中有详细介绍。

使用 <mbean-export/>

此元素在配置基于注解的 MBean 导出文档中进行了详细介绍。

Beans Schema

最后但同样重要的是,我们有 beans Schema 中的元素。这些元素自 Spring 框架诞生之初就已存在。这里不再展示 beans Schema 中各种元素的示例,因为它们已在依赖项和配置详解(以及整个章节)中进行了全面介绍。

请注意,您可以向 <bean/> XML 定义添加零个或多个键值对。如何处理这些额外的元数据完全取决于您自己的自定义逻辑(因此通常只有在您编写自己的自定义元素时才有用,如题为 XML Schema 编写 的附录中所述)。

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

<?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"/> (1)
		<property name="name" value="Rick"/>
	</bean>

</beans>
1 这是示例 meta 元素

对于前面的示例,您可以假设存在一些逻辑,该逻辑使用 bean 定义并建立利用所提供的元数据的缓存基础设施。