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.
|
The |
一个常见的位置(至少在 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,它可能已经被容器初始化。)所有引用最终是对另一个对象的引用。作用域和验证取决于你是否通过 bean
或 parent
属性指定其他对象的 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>
|
The |
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
类型 List
、Set
、Map
和 Properties
的属性和参数。以下示例展示了如何使用它们:
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
集合类型(即值的有序集合的概念)相关联的语义得以保留。父的值先于子列表的所有值。在 Map
、Set
和 Properties
集合类型的情况下,不存在排序。因此,对于容器在内部使用的与关联的 Map
、Set
和 Properties
实现类型相关的集合类型,不存在排序语义。
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
你无法合并不同的集合类型(例如,Map
和 List
)。如果你确实尝试这样做,就会抛出一个适当的 Exception
。merge
属性必须在较低的、继承的子定义中指定。在父集合定义中指定 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.99
、2.75
和 3.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 格式那么灵活。例如,用于申明属性引用的格式与 |
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 |
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 语法,索引符号需要前导 |
Due to the XML grammar, the index notation requires the presence of the leading |
在实践中,构造函数解析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
。为了实现这个,something
的 fred
属性,以及 fred
的 bob
属性在 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.