Dependencies and Configuration in Detail

previous section所述,你可以将 bean 属性和构造器参数定义为对其他已管理的 bean(合作者)的引用,或定义为内联值。Spring 基于 XML 的配置元数据支持其 `<property/>`和 `<constructor-arg/>`元素内的子元素类型以用于此目的。

As mentioned in the previous section, you can define bean properties and constructor arguments as references to other managed beans (collaborators) or as values defined inline. Spring’s XML-based configuration metadata supports sub-element types within its <property/> and <constructor-arg/> elements for this purpose.

Straight Values (Primitives, Strings, and so on)

<property/> 元素的 value 属性将属性或构造函数参数指定为人类可读的字符串表示形式。Spring 的 conversion service 用于将这些值从 String 转换为属性或参数的实际类型。以下示例显示了如何设置各种值:

The value attribute of the <property/> element specifies a property or constructor argument as a human-readable string representation. Spring’s conversion service is used to convert these values from a String to the actual type of the property or argument. The following example shows various values being set:

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
	<!-- results in a setDriverClassName(String) call -->
	<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
	<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
	<property name="username" value="root"/>
	<property name="password" value="misterkaoli"/>
</bean>

以下示例使用 p-namespace 来进行更加简洁的 XML 配置:

The following example uses the p-namespace for even more succinct XML configuration:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	https://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close"
		p:driverClassName="com.mysql.jdbc.Driver"
		p:url="jdbc:mysql://localhost:3306/mydb"
		p:username="root"
		p:password="misterkaoli"/>

</beans>

前面的 XML 代码更为简洁。但是,除非你使用支持在创建 bean 定义时自动完成属性的 IDE(例如 IntelliJ IDEA或https://spring.io/tools[Eclipse 的 Spring 工具]),否则会在运行时而非设计时发现拼写错误。强烈建议使用此类 IDE 帮助。

The preceding XML is more succinct. However, typos are discovered at runtime rather than design time, unless you use an IDE (such as IntelliJ IDEA or the Spring Tools for Eclipse) that supports automatic property completion when you create bean definitions. Such IDE assistance is highly recommended.

您还可以按如下方式配置 java.util.Properties 实例:

You can also configure a java.util.Properties instance, as follows:

<bean id="mappings"
	class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">

	<!-- typed as a java.util.Properties -->
	<property name="properties">
		<value>
			jdbc.driver.className=com.mysql.jdbc.Driver
			jdbc.url=jdbc:mysql://localhost:3306/mydb
		</value>
	</property>
</bean>

Spring 容器使用 JavaBeans PropertyEditor 机制将 <value/> 元素内部的文本转换为一个 java.util.Properties 实例。这是一个很好的快捷方式,也是 Spring 团队在嵌套的 <value/> 元素优于 value 属性样式的一些情况下之一。

The Spring container converts the text inside the <value/> element into a java.util.Properties instance by using the JavaBeans PropertyEditor mechanism. This is a nice shortcut, and is one of a few places where the Spring team do favor the use of the nested <value/> element over the value attribute style.

The idref element

idref 元素只是一种防错方法,可以将容器中另一个 Bean 的 id(一个字符串值 - 而不是引用)传递给 <constructor-arg/><property/> 元素。以下示例演示了如何使用它:

The idref element is simply an error-proof way to pass the id (a string value - not a reference) of another bean in the container to a <constructor-arg/> or <property/> element. The following example shows how to use it:

<bean id="theTargetBean" class="..."/>

<bean id="theClientBean" class="...">
	<property name="targetName">
		<idref bean="theTargetBean"/>
	</property>
</bean>

前面的 Bean 定义片段在运行时完全等同于以下片段:

The preceding bean definition snippet is exactly equivalent (at runtime) to the following snippet:

<bean id="theTargetBean" class="..." />

<bean id="client" class="...">
	<property name="targetName" value="theTargetBean"/>
</bean>

第一种形式优于第二种形式,因为使用 `idref`标记可以让容器在部署时验证引用的命名 bean 是否实际存在。在第二个变量中,不会对传递给 `client`bean 的 `targetName`属性的值执行验证。只有在实际实例化 `client`bean 时才会(很可能出现致命结果)发现拼写错误。如果 `client`bean 是 prototypebean,此拼写错误和由此产生的异常可能只有在部署容器后很长时间内才会被发现。

The first form is preferable to the second, because using the idref tag lets the container validate at deployment time that the referenced, named bean actually exists. In the second variation, no validation is performed on the value that is passed to the targetName property of the client bean. Typos are only discovered (with most likely fatal results) when the client bean is actually instantiated. If the client bean is a prototype bean, this typo and the resulting exception may only be discovered long after the container is deployed.

idref 元素上的 local 属性在 4.0 beansXSD 中不再受支持,因为它不再对常规 bean 引用提供价值。升级到 4.0 架构时,将现有的 idref local 引用更改为 idref bean

The local attribute on the idref element is no longer supported in the 4.0 beans XSD, since it does not provide value over a regular bean reference any more. Change your existing idref local references to idref bean when upgrading to the 4.0 schema.

一个常见的位置(至少在 Spring 2.0 之前的版本中)是 <idref/> 元素在 ProxyFactoryBean bean 定义中进行配置的地方。在指定拦截器名称时使用 <idref/> 元素可防止你拼写错误拦截器 ID。

A common place (at least in versions earlier than Spring 2.0) where the <idref/> element brings value is in the configuration of AOP interceptors in a ProxyFactoryBean bean definition. Using <idref/> elements when you specify the interceptor names prevents you from misspelling an interceptor ID.

References to Other Beans (Collaborators)

ref 元素是一个 <constructor-arg/><property/> 定义元素中的最后一个元素。在这里,你可以将 bean 的指定属性值设置为对另一个由容器管理的 bean(一个协作者)的引用。被引用的 bean 是要设置其属性的 bean 的一个依赖项,并在按需初始化属性之前进行初始化。(如果协作者是一个单例 bean,它可能已经被容器初始化。)所有引用最终是对另一个对象的引用。作用域和验证取决于你是否通过 beanparent 属性指定其他对象的 ID 或名称。

The ref element is the final element inside a <constructor-arg/> or <property/> definition element. Here, you set the value of the specified property of a bean to be a reference to another bean (a collaborator) managed by the container. The referenced bean is a dependency of the bean whose property is to be set, and it is initialized on demand as needed before the property is set. (If the collaborator is a singleton bean, it may already be initialized by the container.) All references are ultimately a reference to another object. Scoping and validation depend on whether you specify the ID or name of the other object through the bean or parent attribute.

通过 <ref/> 标记的 bean 属性指定目标 bean 是最通用的形式,并允许跨引用同一容器或父容器中的任何 bean,无论它是否在同一个 XML 文件中。bean 属性的值可以与目标 bean 的 id 属性相同,也可以与目标 bean 的 name 属性中的一个值相同。以下示例展示了如何使用 ref 元素:

Specifying the target bean through the bean attribute of the <ref/> tag is the most general form and allows creation of a reference to any bean in the same container or parent container, regardless of whether it is in the same XML file. The value of the bean attribute may be the same as the id attribute of the target bean or be the same as one of the values in the name attribute of the target bean. The following example shows how to use a ref element:

<ref bean="someBean"/>

通过 parent 属性指定目标 bean,可以创建对当前容器父容器中 bean 的引用。parent 属性的值可以与目标 bean 的 id 属性或目标 bean 的 name 属性中的一个值相同。目标 bean 必须在当前容器的父容器中。你应该主要在拥有容器层次结构并希望用一个名称相同于父 bean 的代理包装父容器中的现有 bean 时使用这种 bean 引用变体。以下对列出了如何使用 parent 属性:

Specifying the target bean through the parent attribute creates a reference to a bean that is in a parent container of the current container. The value of the parent attribute may be the same as either the id attribute of the target bean or one of the values in the name attribute of the target bean. The target bean must be in a parent container of the current one. You should use this bean reference variant mainly when you have a hierarchy of containers and you want to wrap an existing bean in a parent container with a proxy that has the same name as the parent bean. The following pair of listings shows how to use the parent attribute:

<!-- in the parent context -->
<bean id="accountService" class="com.something.SimpleAccountService">
	<!-- insert dependencies as required here -->
</bean>
<!-- in the child (descendant) context -->
<bean id="accountService" <!-- bean name is the same as the parent bean -->
	class="org.springframework.aop.framework.ProxyFactoryBean">
	<property name="target">
		<ref parent="accountService"/> <!-- notice how we refer to the parent bean -->
	</property>
	<!-- insert other configuration and dependencies as required here -->
</bean>

ref 元素上的 local 属性在 4.0 beansXSD 中不再受支持,因为它不再对常规 bean 引用提供价值。升级到 4.0 架构时,将现有的 ref local 引用更改为 ref bean

The local attribute on the ref element is no longer supported in the 4.0 beans XSD, since it does not provide value over a regular bean reference any more. Change your existing ref local references to ref bean when upgrading to the 4.0 schema.

Inner Beans

<property/><constructor-arg/> 元素内的 <bean/> 元素定义了一个内部 bean,如下例所示:

A <bean/> element inside the <property/> or <constructor-arg/> elements defines an inner bean, as the following example shows:

<bean id="outer" class="...">
	<!-- instead of using a reference to a target bean, simply define the target bean inline -->
	<property name="target">
		<bean class="com.example.Person"> <!-- this is the inner bean -->
			<property name="name" value="Fiona Apple"/>
			<property name="age" value="25"/>
		</bean>
	</property>
</bean>

内部 bean 定义不需要一个已定义的 ID 或名称。如果指定了,容器不会将该值用作标识符。容器还会在创建时忽略 scope 标记,因为内部 bean 始终是匿名的,并且总是与外部 bean 一起创建。无法独立访问内部 bean,也无法将它们注入到封闭 bean 之外的协作者 bean 中。

An inner bean definition does not require a defined ID or name. If specified, the container does not use such a value as an identifier. The container also ignores the scope flag on creation, because inner beans are always anonymous and are always created with the outer bean. It is not possible to access inner beans independently or to inject them into collaborating beans other than into the enclosing bean.

作为一个边缘情况,可以从自定义作用域(例如,包含在单例 bean 中的请求作用域内部 bean)接收销毁回调。内部 bean 实例的创建与它的包含 bean 绑定,但销毁回调让它参与请求作用域的生命周期。这不是一个常见的场景。内部 bean 通常只共享其包含的 bean 的作用域。

As a corner case, it is possible to receive destruction callbacks from a custom scope — for example, for a request-scoped inner bean contained within a singleton bean. The creation of the inner bean instance is tied to its containing bean, but destruction callbacks let it participate in the request scope’s lifecycle. This is not a common scenario. Inner beans typically simply share their containing bean’s scope.

Collections

<list/><set/><map/><props/> 元素分别设置 Java Collection 类型 ListSetMapProperties 的属性和参数。以下示例展示了如何使用它们:

The <list/>, <set/>, <map/>, and <props/> elements set the properties and arguments of the Java Collection types List, Set, Map, and Properties, respectively. The following example shows how to use them:

<bean id="moreComplexObject" class="example.ComplexObject">
	<!-- results in a setAdminEmails(java.util.Properties) call -->
	<property name="adminEmails">
		<props>
			<prop key="administrator">administrator@example.org</prop>
			<prop key="support">support@example.org</prop>
			<prop key="development">development@example.org</prop>
		</props>
	</property>
	<!-- results in a setSomeList(java.util.List) call -->
	<property name="someList">
		<list>
			<value>a list element followed by a reference</value>
			<ref bean="myDataSource" />
		</list>
	</property>
	<!-- results in a setSomeMap(java.util.Map) call -->
	<property name="someMap">
		<map>
			<entry key="an entry" value="just some string"/>
			<entry key="a ref" value-ref="myDataSource"/>
		</map>
	</property>
	<!-- results in a setSomeSet(java.util.Set) call -->
	<property name="someSet">
		<set>
			<value>just some string</value>
			<ref bean="myDataSource" />
		</set>
	</property>
</bean>

映射键或值的值,或者是集合值,也可以是以下任何元素:

The value of a map key or value, or a set value, can also be any of the following elements:

bean | ref | idref | list | set | map | props | value | null

Collection Merging

Spring 容器还支持合并集合。应用程序开发者可以定义一个父 <list/><map/><set/><props/> 元素,并让子 <list/><map/><set/><props/> 元素从父集合继承并覆盖值。也就是说,子集合的值是父集合和子集合元素的元素合并的结果,子集合元素覆盖父集合中指定的值。

The Spring container also supports merging collections. An application developer can define a parent <list/>, <map/>, <set/> or <props/> element and have child <list/>, <map/>, <set/> or <props/> elements inherit and override values from the parent collection. That is, the child collection’s values are the result of merging the elements of the parent and child collections, with the child’s collection elements overriding values specified in the parent collection.

关于合并的这一部分讨论了父项和子项 bean 机制。不熟悉父项和子项 bean 定义的读者可能希望在继续之前先阅读 relevant section

This section on merging discusses the parent-child bean mechanism. Readers unfamiliar with parent and child bean definitions may wish to read the relevant section before continuing.

以下示例演示集合合并:

The following example demonstrates collection merging:

<beans>
	<bean id="parent" abstract="true" class="example.ComplexObject">
		<property name="adminEmails">
			<props>
				<prop key="administrator">administrator@example.com</prop>
				<prop key="support">support@example.com</prop>
			</props>
		</property>
	</bean>
	<bean id="child" parent="parent">
		<property name="adminEmails">
			<!-- the merge is specified on the child collection definition -->
			<props merge="true">
				<prop key="sales">sales@example.com</prop>
				<prop key="support">support@example.co.uk</prop>
			</props>
		</property>
	</bean>
<beans>

请注意在 child bean 定义的 adminEmails 属性的 <props/> 元素中使用了 merge=true 属性。当 child bean 被容器解析和实例化时,结果实例有一个 adminEmails Properties 集合,该集合包含将子 adminEmails 集合与父 adminEmails 集合合并的结果。以下清单显示了结果:

Notice the use of the merge=true attribute on the <props/> element of the adminEmails property of the child bean definition. When the child bean is resolved and instantiated by the container, the resulting instance has an adminEmails Properties collection that contains the result of merging the child’s adminEmails collection with the parent’s adminEmails collection. The following listing shows the result:

administrator=administrator@example.com sales=sales@example.com support=support@example.co.uk

Properties 集合的值集继承父 <props/> 中的所有属性元素,子 support 值的值覆盖了父集合中的值。

The child Properties collection’s value set inherits all property elements from the parent <props/>, and the child’s value for the support value overrides the value in the parent collection.

这种合并行为同样适用于 <list/><map/><set/> 集合类型。在 <list/> 元素的具体情况下,与 List 集合类型(即值的有序集合的概念)相关联的语义得以保留。父的值先于子列表的所有值。在 MapSetProperties 集合类型的情况下,不存在排序。因此,对于容器在内部使用的与关联的 MapSetProperties 实现类型相关的集合类型,不存在排序语义。

This merging behavior applies similarly to the <list/>, <map/>, and <set/> collection types. In the specific case of the <list/> element, the semantics associated with the List collection type (that is, the notion of an ordered collection of values) is maintained. The parent’s values precede all of the child list’s values. In the case of the Map, Set, and Properties collection types, no ordering exists. Hence, no ordering semantics are in effect for the collection types that underlie the associated Map, Set, and Properties implementation types that the container uses internally.

Limitations of Collection Merging

你无法合并不同的集合类型(例如,MapList)。如果你确实尝试这样做,就会抛出一个适当的 Exceptionmerge 属性必须在较低的、继承的子定义中指定。在父集合定义中指定 merge 属性是多余的,不会产生预期的合并。

You cannot merge different collection types (such as a Map and a List). If you do attempt to do so, an appropriate Exception is thrown. The merge attribute must be specified on the lower, inherited, child definition. Specifying the merge attribute on a parent collection definition is redundant and does not result in the desired merging.

Strongly-typed collection

借助 Java 对泛型的支持,你可以使用强类型集合。也就是说,可以声明一个 Collection 类型,使它只能包含(例如)String 元素。如果你使用 Spring 将强类型 Collection 依赖注入到一个 bean 中,你可以利用 Spring 的类型转换支持,这样你的强类型 Collection 实例的元素在添加到 Collection 之前会转换为适当的类型。以下 Java 类和 bean 定义展示了如何做到这一点:

Thanks to Java’s support for generic types, you can use strongly typed collections. That is, it is possible to declare a Collection type such that it can only contain (for example) String elements. If you use Spring to dependency-inject a strongly-typed Collection into a bean, you can take advantage of Spring’s type-conversion support such that the elements of your strongly-typed Collection instances are converted to the appropriate type prior to being added to the Collection. The following Java class and bean definition show how to do so:

  • Java

  • Kotlin

public class SomeClass {

	private Map<String, Float> accounts;

	public void setAccounts(Map<String, Float> accounts) {
		this.accounts = accounts;
	}
}
class SomeClass {
	lateinit var accounts: Map<String, Float>
}
<beans>
	<bean id="something" class="x.y.SomeClass">
		<property name="accounts">
			<map>
				<entry key="one" value="9.99"/>
				<entry key="two" value="2.75"/>
				<entry key="six" value="3.99"/>
			</map>
		</property>
	</bean>
</beans>

something bean 的 accounts 属性准备好注入时,关于强类型 Map<String, Float> 的元素类型的泛型信息可以通过反射获得。因此,Spring 的类型转换基础设施认为各种值元素是 Float 类型,并将字符串值(9.992.753.99)转换为实际的 Float 类型。

When the accounts property of the something bean is prepared for injection, the generics information about the element type of the strongly-typed Map<String, Float> is available by reflection. Thus, Spring’s type conversion infrastructure recognizes the various value elements as being of type Float, and the string values (9.99, 2.75, and 3.99) are converted into an actual Float type.

Null and Empty String Values

Spring 将属性的空参数等视为空字符串。以下基于 XML 的配置元数据片段将 email 属性设置为空字符串值("")。

Spring treats empty arguments for properties and the like as empty Strings. The following XML-based configuration metadata snippet sets the email property to the empty String value ("").

<bean class="ExampleBean">
	<property name="email" value=""/>
</bean>

以下示例等效于以下 Java 代码:

The preceding example is equivalent to the following Java code:

  • Java

  • Kotlin

exampleBean.setEmail("");
exampleBean.email = ""

<null/> 元素处理 null 值。以下列表显示了一个示例:

The <null/> element handles null values. The following listing shows an example:

<bean class="ExampleBean">
	<property name="email">
		<null/>
	</property>
</bean>

前面的配置等效于以下 Java 代码:

The preceding configuration is equivalent to the following Java code:

  • Java

  • Kotlin

exampleBean.setEmail(null);
exampleBean.email = null

XML Shortcut with the p-namespace

p 命名空间允许您使用 bean 元素的属性(而不是嵌套的 <property/> 元素)来描述您的属性值、协同 Bean,或两者。

The p-namespace lets you use the bean element’s attributes (instead of nested <property/> elements) to describe your property values collaborating beans, or both.

Spring 支持基于 XML 架构定义的可扩展配置格式 with namespaces。本章讨论的 `beans`配置格式在 XML 架构文档中进行定义。但是,p 命名空间未在 XSD 文件中定义,仅存在于 Spring 的核心之中。

Spring supports extensible configuration formats with namespaces, which are based on an XML Schema definition. The beans configuration format discussed in this chapter is defined in an XML Schema document. However, the p-namespace is not defined in an XSD file and exists only in the core of Spring.

以下示例展示了两个 XML 代码段(第一个使用标准 XML 格式,第二个使用 p 命名空间),它们解析为相同的结果:

The following example shows two XML snippets (the first uses standard XML format and the second uses the p-namespace) that resolve to the same result:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean name="classic" class="com.example.ExampleBean">
		<property name="email" value="someone@somewhere.com"/>
	</bean>

	<bean name="p-namespace" class="com.example.ExampleBean"
		p:email="someone@somewhere.com"/>
</beans>

示例展示了 Bean 定义中 p 命名空间中的一个属性,名为 email。这告诉 Spring 包含一个属性声明。如前所述,p 命名空间没有 Schema 定义,因此您可以将属性的名称设为该属性的名称。

The example shows an attribute in the p-namespace called email in the bean definition. This tells Spring to include a property declaration. As previously mentioned, the p-namespace does not have a schema definition, so you can set the name of the attribute to the property name.

接下来的这个示例包含两个 Bean 定义,它们都引用了另一个 Bean:

This next example includes two more bean definitions that both have a reference to another bean:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean name="john-classic" class="com.example.Person">
		<property name="name" value="John Doe"/>
		<property name="spouse" ref="jane"/>
	</bean>

	<bean name="john-modern"
		class="com.example.Person"
		p:name="John Doe"
		p:spouse-ref="jane"/>

	<bean name="jane" class="com.example.Person">
		<property name="name" value="Jane Doe"/>
	</bean>
</beans>

此示例不仅使用 p 命名空间包含一个属性值,还使用一种特殊格式来声明属性引用。第一个 Bean 定义使用 <property name="spouse" ref="jane"/> 从 Bean john 创建到 Bean jane 的引用,而第二个 Bean 定义使用 p:spouse-ref="jane" 作为一个属性来执行完全相同的操作。在这种情况下,spouse 是属性名称,而 -ref 部分指示这不是一个直接值,而是对另一个 Bean 的引用。

This example includes not only a property value using the p-namespace but also uses a special format to declare property references. Whereas the first bean definition uses <property name="spouse" ref="jane"/> to create a reference from bean john to bean jane, the second bean definition uses p:spouse-ref="jane" as an attribute to do the exact same thing. In this case, spouse is the property name, whereas the -ref part indicates that this is not a straight value but rather a reference to another bean.

p 命名空间没有标准 XML 格式那么灵活。例如,用于申明属性引用的格式与 Ref 结尾的属性发生冲突,而标准 XML 格式不会。我们建议你谨慎地选择方法,并告知你的团队成员,以免生成同时使用所有三种方法的 XML 文档。

The p-namespace is not as flexible as the standard XML format. For example, the format for declaring property references clashes with properties that end in Ref, whereas the standard XML format does not. We recommend that you choose your approach carefully and communicate this to your team members to avoid producing XML documents that use all three approaches at the same time.

XML Shortcut with the c-namespace

类似于 XML Shortcut with the p-namespace,Spring 3.1 中引入的 c 命名空间允许以内联属性来配置构造函数参数,而不是嵌套 constructor-arg 元素。

Similar to the XML Shortcut with the p-namespace, the c-namespace, introduced in Spring 3.1, allows inlined attributes for configuring the constructor arguments rather then nested constructor-arg elements.

以下示例使用 c: 命名空间执行与 Constructor-based Dependency Injection 中相同的操作:

The following example uses the c: namespace to do the same thing as the from Constructor-based Dependency Injection:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:c="http://www.springframework.org/schema/c"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="beanTwo" class="x.y.ThingTwo"/>
	<bean id="beanThree" class="x.y.ThingThree"/>

	<!-- traditional declaration with optional argument names -->
	<bean id="beanOne" class="x.y.ThingOne">
		<constructor-arg name="thingTwo" ref="beanTwo"/>
		<constructor-arg name="thingThree" ref="beanThree"/>
		<constructor-arg name="email" value="something@somewhere.com"/>
	</bean>

	<!-- c-namespace declaration with argument names -->
	<bean id="beanOne" class="x.y.ThingOne" c:thingTwo-ref="beanTwo"
		c:thingThree-ref="beanThree" c:email="something@somewhere.com"/>

</beans>

c: 命名空间使用与 p: 命名空间(bean 引用后缀为 -ref)相同的约定来按名称设置构造函数参数。类似地,它需要在 XML 文件中声明,尽管它未在 XSD Schema 中定义(它存在于 Spring core 中)。

The c: namespace uses the same conventions as the p: one (a trailing -ref for bean references) for setting the constructor arguments by their names. Similarly, it needs to be declared in the XML file even though it is not defined in an XSD schema (it exists inside the Spring core).

对于构造函数参数名称不可用的罕见情况(通常是在未包含调试信息的情况下编译字节码时),您可以回退到参数索引,如下所示:

For the rare cases where the constructor argument names are not available (usually if the bytecode was compiled without debugging information), you can use fallback to the argument indexes, as follows:

<!-- c-namespace index declaration -->
<bean id="beanOne" class="x.y.ThingOne" c:_0-ref="beanTwo" c:_1-ref="beanThree"
	c:_2="something@somewhere.com"/>

由于 XML 语法,索引符号需要前导 _,因为 XML 属性名称不能以数字开头(即使一些 IDE 允许这样做)。对于 <constructor-arg> 元素,也有相应的索引符号,但由于声明的普通顺序通常在那里足够,因此并不常用。

Due to the XML grammar, the index notation requires the presence of the leading _, as XML attribute names cannot start with a number (even though some IDEs allow it). A corresponding index notation is also available for <constructor-arg> elements but not commonly used since the plain order of declaration is usually sufficient there.

在实践中,构造函数解析mechanism 在匹配参数方面非常有效,所以除非你真的需要,否则我们建议在你的整个配置中使用名称符号。

In practice, the constructor resolution mechanism is quite efficient in matching arguments, so unless you really need to, we recommend using the name notation throughout your configuration.

Compound Property Names

当您设置 Bean 属性时,您可以使用复合或嵌套的属性名称,只要路径的所有要素(最后一个属性名称除外)不是 null。考虑以下 Bean 定义:

You can use compound or nested property names when you set bean properties, as long as all components of the path except the final property name are not null. Consider the following bean definition:

<bean id="something" class="things.ThingOne">
	<property name="fred.bob.sammy" value="123" />
</bean>

something Bean 有一个 fred 属性,它有一个 bob 属性,它有一个 sammy 属性,并且最后那个 sammy 属性被设为值 123。为了实现这个,somethingfred 属性,以及 fredbob 属性在 Bean 构建后不能为 null。否则,将会抛出 NullPointerException

The something bean has a fred property, which has a bob property, which has a sammy property, and that final sammy property is being set to a value of 123. In order for this to work, the fred property of something and the bob property of fred must not be null after the bean is constructed. Otherwise, a NullPointerException is thrown.