XML Schemas

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

util Schema

顾名思义,util 标签处理通用的、实用性的配置问题,例如配置集合、引用常量等。 要使用 util 模式中的标签,您需要在 Infra 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="infra.beans.factory.config.FieldRetrievingFactoryBean" />
  </property>
</bean>

前面的配置使用 Infra FactoryBean 实现(FieldRetrievingFactoryBean) 将 bean 上的 isolation 属性的值设置为 java.sql.Connection.TRANSACTION_SERIALIZABLE 常量的值。 这很好,但它很冗长,并且(不必要地)向最终用户公开了 Infra 内部管道。

以下基于 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 的属性值或构造函数参数。

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

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

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

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

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

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

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

在 Infra 中,将枚举值作为属性或构造函数参数注入到 bean 中很容易。 您实际上不必做任何事情,也不必了解 Infra 内部的任何信息(甚至不必了解诸如 FieldRetrievingFactoryBean 之类的类)。 以下示例枚举显示了注入枚举值是多么容易:

  • Java

package jakarta.persistence;

public enum PersistenceContextType {

  TRANSACTION,
  EXTENDED
}

现在考虑以下类型为 PersistenceContextType 的 setter 和相应的 bean 定义:

  • Java

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>

使用 <util:property-path/>

考虑以下示例:

<!-- target bean to be referenced by name -->
<bean id="testBean" class="infra.beans.TestBean" scope="prototype">
  <property name="age" value="10"/>
  <property name="spouse">
    <bean class="infra.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="infra.beans.factory.config.PropertyPathFactoryBean"/>

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

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

<!-- target bean to be referenced by name -->
<bean id="testBean" class="infra.beans.TestBean" scope="prototype">
  <property name="age" value="10"/>
  <property name="spouse">
    <bean class="infra.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="infra.beans.TestBean" scope="prototype">
  <property name="age" value="10"/>
  <property name="spouse">
    <bean class="infra.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="infra.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="infra.beans.factory.config.PropertyPathFactoryBean">
  <property name="targetObject">
    <bean class="infra.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="infra.beans.factory.config.PropertyPathFactoryBean"/>

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

<bean id="..." class="...">
  <property name="age">
    <bean id="person.age"
        class="infra.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="infra.beans.factory.config.PropertiesFactoryBean">
  <property name="location" value="classpath:com/foo/jdbc-production.properties"/>
</bean>

前面的配置使用 Infra 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="infra.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>

前面的配置使用 Infra 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="infra.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>

前面的配置使用 Infra 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="infra.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>

前面的配置使用 Infra 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 标签处理 Infra 中所有 AOP 的配置,包括 Infra 自己的基于代理的 AOP 框架以及 Infra 与 AspectJ AOP 框架的集成。 这些标签在名为 Infra 面向切面编程 的一章中进行了全面介绍。

为了完整起见,要使用 aop 模式中的标签,您需要在 Infra 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 Schema

context 标签处理与管道相关的 ApplicationContext 配置——即通常不是对最终用户重要的 bean,而是做很多 Infra “苦力”工作的 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/>

此元素激活 ${…​} 占位符的替换,这些占位符将针对指定的属性文件(作为资源位置)进行解析。 此元素是一种方便的机制,可为您设置 PropertySourcesPlaceholderConfigurer。 如果您需要更好地控制特定的 PropertySourcesPlaceholderConfigurer 设置,您可以自己将其显式定义为 bean。

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

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

使用 <annotation-config/>

此元素激活 Infra 基础设施以检测 bean 类中的注解:

  • Infra @Configuration 模型

  • @Autowired/@Inject, @Value, 和 @Lookup

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

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

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

  • Infra @EventListener

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

此元素不激活 Infra @Transactional 注解的处理; 为此目的,您可以使用 <tx:annotation-driven/> 元素。 同样,Infra 缓存注解 也需要显式 启用

使用 <component-scan/>

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

使用 <load-time-weaver/>

此元素在 在 TODAY Framework 中使用 AspectJ 进行加载时编织 一节中有详细说明。

使用 <infra-configured/>

此元素在 使用 AspectJ 依赖注入 Infra 域对象 一节中有详细说明。

使用 <mbean-export/>

此元素在 配置基于注解的 MBean 导出 一节中有详细说明。

beans Schema

最后但同样重要的是,我们有 beans 模式中的元素。这些元素从框架诞生之初就存在于 Infra 中。 这里没有显示 beans 模式中各种元素的示例,因为它们在 依赖项和配置详解 (实际上,在整个 )中都有非常全面的介绍。

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

以下示例显示了周围 <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"/> (1)
    <property name="name" value="Rick"/>
  </bean>

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

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