XML模式

附录的这部分列出了与核心容器相关的XML模式。

实用工具util模式

正如其名称所示,util标签处理常见的实用配置问题,例如配置集合、引用常量等。要在util模式中使用标签,您需要在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 -->

</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,用于检索static或非静态字段值。通常用于检索public static final常量,然后可以用于设置另一个bean的属性值或构造函数参数。

以下示例展示了如何公开一个static字段,通过使用staticField属性:

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

还有一种方便的用法形式,其中将static字段指定为bean名称,如以下示例所示:

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

这意味着不再有选择bean id的余地(因此任何引用它的其他bean也必须使用这个更长的名称),但这种形式非常简洁定义和作为内部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/>

考虑以下示例:

<!-- 要被名称引用的目标bean -->
<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>

<!-- 结果为 10,即 'testBean' bean 的 'age' 属性的值 -->
<bean id="testBean.age" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>

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

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

<!-- 要被名称引用的目标bean -->
<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>

<!-- 结果为 10,即 'testBean' bean 的 'age' 属性的值 -->
<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(按名称)使用路径的情况:

<!-- 要被名称引用的目标bean -->
<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>

<!-- 结果为 11,即 'person' bean 的 'spouse.age' 属性的值 -->
<bean id="theAge"
		class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
	<property name="targetBeanName" value="person"/>
	<property name="propertyPath" value="spouse.age"/>
</bean>

在以下示例中,路径针对内部bean进行了评估:

<!-- 结果为 12,即内部bean的 'age' 属性的值 -->
<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名称是属性路径。以下示例展示了快捷形式:

<!-- 结果为 10,即 'person' bean 的 'age' 属性的值 -->
<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/>

考虑以下示例:

<!-- 使用从提供的位置加载的值创建一个java.util.Properties实例 -->
<bean id="jdbcConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
	<property name="location" value="classpath:com/foo/jdbc-production.properties"/>
</bean>

上述配置使用了一个Spring FactoryBean实现(PropertiesFactoryBean),实例化了一个带有从提供的Resource位置加载的值的 java.util.Properties 实例。

以下示例使用了一个 util:properties 元素,以更简洁的方式表示:

<!-- 使用从提供的位置加载的值创建一个java.util.Properties实例 -->
<util:properties id="jdbcConfiguration" location="classpath:com/foo/jdbc-production.properties"/>

使用 <util:list/>

考虑以下示例:

<!-- 使用从提供的 'sourceList' 加载的值创建一个 java.util.List 实例 -->
<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/>元素来提供更简洁的表示:

<!-- 使用提供的值创建一个 java.util.List 实例 -->
<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/>

考虑以下示例:

<!-- 使用从提供的 'sourceMap' 加载的值创建一个 java.util.Map 实例 -->
<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/>元素来提供更简洁的表示:

<!-- 使用提供的键值对创建一个 java.util.Map 实例 -->
<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/>

考虑以下示例:

<!-- 使用从提供的 'sourceSet' 加载的值创建一个 java.util.Set 实例 -->
<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)来创建一个初始化为从提供的 sourceSet 中取出的值的 java.util.Set 实例。

以下示例使用了一个 <util:set/> 元素来提供更简洁的表示:

<!-- 使用提供的值创建一个 java.util.Set 实例 -->
<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模式

aop标签处理Spring中所有与AOP相关的事务,包括Spring自身基于代理的AOP框架以及Spring与AspectJ AOP框架的集成。这些标签在名为Spring中的面向切面编程的章节中有详细介绍。

为了完整起见,在Spring XML配置文件的顶部使用aop模式的标签,您需要包含以下前言(片段中的文本引用了正确的模式,以便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模式

context标签处理与ApplicationContext配置相关的管道工作,通常不是对最终用户重要的bean,而是在Spring中执行大部分“繁重”工作的bean,例如BeanfactoryPostProcessors。以下片段引用了正确的模式,以便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框架中使用AspectJ进行加载时织入部分有详细介绍。

使用<spring-configured/>

此元素在使用AspectJ将域对象依赖注入Spring部分有详细介绍。

使用<mbean-export/>

此元素在配置基于注解的MBean导出部分有详细介绍。

Beans模式

最后,我们有beans模式中的元素。这些元素从Spring框架的最初开始就存在。这里没有展示beans模式中各种元素的示例,因为它们在详细的依赖和配置(以及整个章节)中得到了全面覆盖。

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

以下示例展示了<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定义并设置使用提供的元数据的缓存基础设施。