XML模式
附录的这一部分列出了与核心容器相关的XML模式(XML schemas)。
util Schema
顾名思义,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 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,用于获取静态(static)或非静态(non-static)字段的值。它通常用于获取 public、static、final 常量,这些常量随后可以用来设置另一个 bean 的属性值或构造函数参数。
以下示例展示了如何通过使用 staticField 属性来暴露一个 static 字段:
<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引用来说,不需要指定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>pechorin@hero.org</value>
<value>raskolnikov@slums.org</value>
<value>stavrogin@gov.org</value>
<value>porfiry@gov.org</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>pechorin@hero.org</value>
<value>raskolnikov@slums.org</value>
<value>stavrogin@gov.org</value>
<value>porfiry@gov.org</value>
</util:list>
您还可以通过在<util:list/>元素上使用list-class属性来明确控制实例化并填充的List的具体类型。例如,如果我们确实需要实例化一个java.utilLinkedList,我们可以使用以下配置:
<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>
如果没有提供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="pechorin@hero.org"/>
<entry key="raskolnikov" value="raskolnikov@slums.org"/>
<entry key="stavrogin" value="stavrogin@gov.org"/>
<entry key="porfiry" value="porfiry@gov.org"/>
</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="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>
你也可以通过在 <util:map/> 元素上使用 'map-class' 属性来明确控制实例化并填充的 Map 的具体类型。例如,如果我们确实需要实例化一个 java.util.TreeMap,我们可以使用以下配置:
<util:map id="emails" map-class="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>
如果没有提供'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>pechorin@hero.org</value>
<value>raskolnikov@slums.org</value>
<value>stavrogin@gov.org</value>
<value>porfiry@gov.org</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>pechorin@hero.org</value>
<value>raskolnikov@slums.org</value>
<value>stavrogin@gov.org</value>
<value>porfiry@gov.org</value>
</util:set>
您还可以通过使用 <util:set/> 元素上的 set-class 属性来明确控制实例化并填充的 Set 的确切类型。例如,如果我们确实需要实例化一个 java.util.TreeSet,我们可以使用以下配置:
<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>
如果没有提供 set-class 属性,容器将选择一种 Set 的实现方式。
aop 模式
<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>
context 架构
context 标签用于处理与基础配置(plumbing)相关的 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的caching annotations也需要被显式启用。
使用 <component-scan/>
该元素的详细信息可以在基于注解的容器配置部分找到。
使用 <load-time-weaver/>
使用 <spring-configured/>
该元素在使用AspectJ通过Spring进行领域对象依赖注入一节中有详细说明。
使用 <mbean-export/>
此元素的详细信息请参见配置基于注释的MBean导出部分。
Beans Schema
最后但同样重要的是,我们还有beans模式中的元素。这些元素从Spring框架诞生之初就存在了。这里没有展示beans模式中各种元素的示例,因为它们在dependencies and configuration in detail中有非常全面的介绍(实际上,在整个chapter中也有相关内容)。
请注意,你可以在<bean/> XML定义中添加零个或多个键值对。这些额外元数据的具体处理方式完全取决于你自己的自定义逻辑(因此,通常只有在你按照附录《XML模式编写》(xml-custom.md)中的描述来编写自己的自定义元素时,这些元数据才会发挥作用)。
以下示例展示了 <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>
这是
meta元素的示例
在前面的例子中,你可以假设存在某种逻辑,它消费bean定义并设置一些缓存基础设施,这些基础设施会使用提供的元数据。