References to Other Beans (Collaborators)
对其他bean的引用(协作者)
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元素是<constructor-arg/>
或 <property/>
·定义元素中的最后一个元素。在这里,您将bean的指定属性的值设置为对容器管理的另一个bean(协作者)的引用。被引用的bean是要设置其属性的bean的依赖项,并且在设置属性之前根据需要对其进行初始化。(如果collaborator
是一个单例bean,那么它可能已经被容器初始化了。)所有引用最终都是对另一个对象的引用。作用域和验证取决于是否通过bean或父属性指定另一个对象的ID或名称。
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属性指定目标bean是最常见的形式,它允许创建对同一容器或父容器中任何bean的引用,而不管它是否在同一个XML文件中。bean属性的值可以与目标bean的id属性相同,也可以与目标bean的name属性中的某个值相同。以下示例显示如何使用ref元素:
<ref bean="someBean"/>
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:
通过parent
属性指定目标bean
将创建对当前容器的父容器中的bean的引用。父属性的值可以与目标bean的id属性或目标bean的name属性中的某个值相同。目标bean必须位于当前bean的父容器中。您应该使用这个bean引用变量,主要是当您有一个容器的层次结构,并且您想用一个与父bean同名的代理将现有的bean包装在父容器中。以下两个列表显示了如何使用parent属性:
<!-- in the parent context -->
<bean id="accountService" class="com.something.SimpleAccountService">
<!-- insert dependencies as required as 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 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. |
|
---|---|
4.0beans xsd不再支持ref元素上的local属性,因为它不再提供常规bean引用的值。在升级到4.0模式时,将现有的ref本地引用更改为ref bean。 |
Inner Beans
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>
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定义不需要定义的ID或名称。如果指定,则容器不使用此值作为标识符。容器在创建时也会忽略范围标志,因为内部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.
例如,从一个单独的bean到一个单独的bean的作用域,比如一个调用bean。内部bean实例的创建与其包含的bean相关联,但是销毁回调允许它参与请求范围的生命周期。这种情况并不常见。内部bean通常只共享它们的包含bean的范围。
Collections
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:
<list/>、<set/>、<map/>和<props/>元素分别设置Java集合类型list、set、map和properties的属性和参数。下面的示例演示如何使用它们:
<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
集合合并
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.
Spring容器还支持合并集合。应用程序开发人员可以定义父元素<list/>、<map/>、<set/>或<props/>元素,并让子元素<list/>、<map/>、<set/>或<props/>继承并重写父集合中的值。也就是说,子集合的值是合并父集合和子集合的元素的结果,子集合元素覆盖父集合中指定的值。
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.
关于合并的这一节讨论了父子bean机制。不熟悉父bean和子bean定义的读者可能希望在继续之前阅读相关部分。
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>
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:
注意在子bean定义的adminEmails属性的<props/>元素上使用了merge=true属性。当容器解析并实例化子bean时,生成的实例具有一个adminEmails Properties集合,该集合包含将子级的adminEmails集合与父级的adminEmails集合合并的结果。下面的列表显示了结果:
administrator=administrator@example.com
sales=sales@example.com
support=support@example.co.uk
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.
子Properties集合的值集继承父集合<props/>中的所有属性元素,子级的支持值的值覆盖父集合中的值。
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.
此合并行为类似于<list/>、<map/>和<set/>集合类型。在<list/>元素的特定情况下,与list collection类型相关联的语义(即值的有序集合的概念)被维护。父项的值先于所有子项列表的值。对于Map、Set和Properties集合类型,不存在排序。因此,对于容器内部使用的关联映射、集和属性实现类型的集合类型,没有有效的排序语义。
Limitations of Collection Merging
集合合并的局限性
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.
不能合并不同的集合类型(如映射和列表)。如果您确实尝试这样做,则会引发适当的异常。必须在较低的继承子定义上指定merge属性。在父集合定义上指定merge属性是多余的,不会导致所需的合并。
Strongly-typed collection
强类型集合
With the introduction of generic types in Java 5, 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:
随着Java5中泛型类型的引入,您可以使用强类型集合。也就是说,可以声明一个集合类型,使其只能包含(例如)字符串元素。如果使用Spring将强类型集合注入bean中,那么可以利用Spring的类型转换支持,以便在将强类型集合实例的元素添加到集合之前将其转换为适当的类型。下面的Java类的定义如下:
Java
public class SomeClass {
private Map<String, Float> accounts;
public void setAccounts(Map<String, Float> accounts) {
this.accounts = accounts;
}
}
<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>
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.
当something bean的accounts属性准备好注入时,关于强类型Map<String,Float>的元素类型的泛型信息可以通过反射获得。因此,Spring的类型转换基础设施将各种值元素识别为Float类型,字符串值(9.99、2.75和3.99)转换为实际的Float类型。