官方英文版地址:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html
备注:翻译如有不对,请多指正,谢谢。
依赖与配置详解
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
and
elements for this purpose.
如前面章节所述,你可以定义bean属性或者构造函数参数用来引用其他被管理的协作beans,或者内置的基本类型值。Spring的基于XML的配置元数据支持在
Straight values (primitives, Strings, and so on)
The value
attribute of the
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 uses the p-namespace for even more succinct XML configuration.
下面的例子使用p命名空间( p-namespace)来完成更简洁的XML配置。
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 Tool Suite (STS) that support automatic property completion when you create bean definitions. Such IDE assistance is highly recommended.
前面的XML更加简洁,然后,除非你使用像IntelliJ IDEA或者Spring Tool Suite(STS)类似的支持在进行bean定义时自动属性填充的IDE,否则将会在运行时而不是在设计时才会发现拼写错误。强烈推荐使用这些IDE的这类帮助功能。
You can also configure a java.util.Properties
instance as:
你可以配置java.util.Properties实例如下所示:
jdbc.driver.className=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
The Spring container converts the text inside the
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
element over the value
attribute style.
Spring容器使用JavaBeans的PropertyEditor自动将
The idref element
The idref
element is simply an error-proof way to pass the id (string value - not a reference) of another bean in the container to a
or
element.
idref元素是一种将容器中另外一个bean元素的id传递给
The above bean definition snippet is exactly equivalent (at runtime) to the following snippet:
上面的bean定义和下面的效果是相同的。
The first form is preferable to the second, because using the idref
tag allows the container to 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标签可以使容器在发布时间校验引用的bean真实存在。在第二个变体中,不会在client对象的targetName属性上设置的值进行任何校验。只有在client初始化时才会发现输入错误(可能导致严重的后果)。如果client是原型bean,这种类型和由此产生的异常可能在容器部署之后很长时间才会发现。
A common place (at least in versions earlier than Spring 2.0) where the
element brings value is in the configuration of AOP interceptors in a ProxyFactoryBean
bean definition. Using
elements when you specify the interceptor names prevents you from misspelling an interceptor id.
References to other beans (collaborators)
The ref
element is the final element inside a
or
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 will be set, and it is initialized on demand as needed before the property is set. (If the collaborator is a singleton bean, it may be initialized already by the container.) All references are ultimately a reference to another object. Scoping and validation depend on whether you specify the id/name of the other object through the bean
, local,
or parent
attributes.
ref元素是
Specifying the target bean through the bean
attribute of the 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 as one of the values in the name
attribute of the target bean.
不管是否是在相同的xml文件中,通过标签的bean属性指定目标bean是最常用的形式,并且允许创建对相同容器或者父容器中任何bean的引用。元素的bean属性可能和目标bean的id属性或者name属性值中的任何一个值相同。
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, and the target bean must be in a parent container of the current one. You 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 will have the same name as the parent bean.
通过parent属性来指定目标bean,会创建一个对当前容器父容器中bean对象的引用。parent属性的值可能和目标bean的id相同,异或是和目标bean的name属性值的任何一个值相同,而目标bean必须在当前容器的父容器中。你可以使用这个bean的引用的变体,当你知道这个容器的层次结构并且用一个和父类bean同名的代理时,你通常会使用这个bean的变体。
class="org.springframework.aop.framework.ProxyFactoryBean">
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 anymore. Simply change your existing ref local
references to ref bean
when upgrading to the 4.0 schema.
元素的local属性,由于不支持常规bean引用之外的值,所以在4.0 beans xsd中已经不再支持。当升级到4.0的时候,只需要简单的将存在的ref local引用改为ref bean引用即可。
Inner beans
A
element inside the
or
elements defines a so-called inner 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: Inner beans are always anonymous and they are always created with the outer bean. It is not possible to inject inner beans into collaborating beans other than into the enclosing bean or to access them independently.
内部类定义并不需要声明的Id或者name属性,如果指定的话,容器也不会使用它们作为唯一标识符。容器在创建的时候也会忽略scope标识:内部bean总是匿名的,并且和包含它的外部bean一起被创建。除了将内部bean注入到封闭bean以外,想要将内部bean注入到协作对象bean中或者独立的访问它们是不可能的。
As a corner case, it is possible to receive destruction callbacks from a custom scope, e.g. for a request-scoped inner bean contained within a singleton bean: The creation of the inner bean instance will be tied to its containing bean, but destruction callbacks allow it to 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的创建是和包含它的容器联系在一起的,但是销毁回调允许在请求作用域声明周期内发生。这并不是常见的场景,内部类一般简单的和包含它的容器拥有相同的作用域。
Collections
In the
,
, , and
elements, you set the properties and arguments of the Java Collection
types List
, Set
, Map
, and Properties
, respectively.
在、
[email protected]
[email protected]
[email protected]
just some string
The value of a map key or value, or a set value, can also again be any of the following elements:
map结构的key或者value值,以及set结构的值,可以是下面几种类型中的任何一种。
bean | ref | idref | list | set | map | props | value | null
Collection merging
The Spring container also supports the merging of collections. An application developer can define a parent-style
, ,
or
element, and have child-style
, ,
or
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容器支持集合的合并。应用程序开发者可以定义一个父类型的、、
、、
The following example demonstrates collection merging:
接下来的例子展示了集合的合并:
[email protected]
[email protected]
[email protected]
[email protected]
Notice the use of the merge=true
attribute on the
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 the merging of the child’s adminEmails
collection with the parent’s adminEmails
collection.
注意,在子bean定义的adminEmails属性上使用了merge=true属性。当容器子bean被解析和初始化的时候,生成的实例有一个adminEmails属性集合,这个集合中包含了父集合和子集合中的所有元素。
[email protected]
[email protected]
[email protected]
The child Properties
collection’s value set inherits all property elements from the parent
, and the child’s value for the support
value overrides the value in the parent collection.
子集合中的Properties,继承了父元素
This merging behavior applies similarly to the
, , and
collection types. In the specific case of the
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.
这个合并的行为在、、
这个特殊的例子中,维护中集合中元素的顺序,和Java类型List的元素的顺序和
元素中定义的顺序一致,父集合中的值在子集合中的值的前面。在Map、Set和Properties集合类型中,不会维护元素的顺序。对于内部使用关联映射的类型,没有任何排序语义。
Limitations of collection merging
You cannot merge different collection types (such as a Map
and a List
), and 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 will not result in the desired merging.
你不能将不同集合类型(如Map和List)进行合并,如果你尝试去这么做,将会抛出一个异常。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 String
elements (for example). If you are using 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
.
伴随着Java5之后泛型类型的引入,你可以使用强类型集合。这就是说,可以定义一个集合类型值包含String元素(举个例子)成为可能。如果你使用Spring将强类型集合注入到bean中,你可以充分利用Spring的类型转换支持,以便在将元素添加到集合前将这些元素转换为合适的类型。
public class Foo {
private Map accounts;
public void setAccounts(Map accounts) {
this.accounts = accounts;
}
}
When the accounts
property of the foo
bean is prepared for injection, the generics information about the element type of the strongly-typed Map
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.
当foo这个bean的accounts属性开始准备被注入的时候,强类型Map
Null and empty string values
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 ("").
Spring将空参数视为空字符串。下面基于XML的配置元数据将email属性的值设置为空字符串。
The preceding example is equivalent to the following Java code:
前面例子等同于下面的Java代码:
exampleBean.setEmail("");
The
element handles null
values. For example:
The above configuration is equivalent to the following Java code:
上面的配置等同于Java代码:
exampleBean.setEmail(null);
XML shortcut with the p-namespace
The p-namespace enables you to use the bean
element’s attributes, instead of nested
elements, to describe your property values and/or collaborating beans.
你可以使用p命名空间,而不是
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.
Spring支持使用命名空间形式的扩展配置,在本章中讨论的bean配置是以XML文档的方式定义的,然而,p命名空间并不是在XSD文件中定义,只在Spring的核心中存在。
The following example shows two XML snippets that resolve to the same result: The first uses standard XML format and the second uses the p-namespace.
接下来的例子中展示了两个XML的配置片段具有相同的结果:第一个使用标准的XML形式,第二个使用p命名空间。
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定义中有个使用p命名空间定义的email属性。p命名空间告诉Spring包含一个属性声明。如前面说明,p命名空间没有模式定义,在p后面可以设置属性的名称。
This next example includes two more bean definitions that both have a reference to another bean:
接下来的例子包含了两个bean的定义,每个bean定义都包含了对其他bean的引用。
As you can see, 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
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命名空间的property值,还包含了特殊形式声明的property引用。第一个bean定义使用
XML shortcut with the c-namespace
Similar to the XML shortcut with the p-namespace, the c-namespace, newly introduced in Spring 3.1, allows usage of inlined attributes for configuring the constructor arguments rather then nested constructor-arg
elements.
和p命名空间相似,c命名空间,是在Spring3.1之后才引入的,可以使用内联属性来配置构造参数,而不是使用
Let’s review the examples from Constructor-based dependency injection with the c:
namespace:
让我们使用c命名空间来回顾下基于构造函数依赖注入的例子。
The c:
namespace uses the same conventions as the p:
one (trailing -ref
for bean references) for setting the constructor arguments by their names. And just as well, it needs to be declared even though it is not defined in an XSD schema (but it exists inside the Spring core).
c命名空间使用和p命名空间相同的转换形式来设置构造参数,末尾使用-ref来标识bean引用。即使在XSD模式中没有定义,单同样需要声明它。
For the rare cases where the constructor argument names are not available (usually if the bytecode was compiled without debugging information), one can use fallback to the argument indexes:
对于构造函数参数名不可用的情况,可以使用构造函数参数索引的方式进行设置。
In practice, the constructor resolution mechanism is quite efficient in matching arguments so unless one really needs to, we recommend using the name notation through-out your configuration.
实际上,构造函数解析在匹配参数方面非常有效,因此,除非确实需要,否则,我们建议在配置中使用基于参数名的符号。
Compound property names
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属性的时候使用复合或者嵌套属性名称,只要这个路径下的所有组件都不是null,考虑下面的bean定义:
The foo
bean has a fred
property, which has a bob
property, which has a sammy
property, and that final sammy
property is being set to the value 123
. In order for this to work, the fred
property of foo
, and the bob
property of fred
must not be null
after the bean is constructed, or a NullPointerException
is thrown.
foo这个bean有一个fred属性,而fred属性含有一个bob属性,这个bob属性又含有一个sammy属性,这个sammy属性的值为123。为了使这个配置生效,在bean被创建之后,fred属性和bob属性都不能为null,否则将抛出一个空指针异常。
Using depends-on
If a bean is a dependency of another bean, that usually means that one bean is set as a property of another. Typically you accomplish this with the element in XML-based configuration metadata. However, sometimes dependencies between beans are less direct. An example is when a static initializer in a class needs to be triggered, such as for database driver registration. The
depends-on
attribute can explicitly force one or more beans to be initialized before the bean using this element is initialized. The following example uses the depends-on
attribute to express a dependency on a single bean:
如果一个Bean是另一个Bean的依赖,这往往意味着这个Bean是另一个Bean的一个属性。一般来说,你可能通过在XML配置元数据中使用元素来进行实现。然而,有时候Bean之间的依赖并不是太直接。举个例子,正如在一个类的静态初始化器,如数据库驱动程序注册,需要被触发。depends-on属性可以显示的要求一个或者多个bean在使用它们的Bean初始化前被初始化。下面的例子使用了depends-on属性来描述了一个对简单Bean的依赖。
To express a dependency on multiple beans, supply a list of bean names as the value of the depends-on
attribute (commas, whitespace, and semicolons are valid delimiters):
为了表达对多个Bean的依赖,可以给depends-ons属性提供一个bean名称的列表作为属性值(逗号、空格和分号都是有效的分隔符):
The depends-on
attribute can specify both an initialization-time dependency and, in the case of singleton beans only, a corresponding destruction-time dependency. Dependent beans that define a depends-on
relationship with a given bean are destroyed first, prior to the given bean itself being destroyed. Thus, depends-on
can also control shutdown order.
depends-on属性既可以指定初始化时间依赖性,也可以指定相应的销毁时间依赖性。 在给定的bean本身被销毁之前,首先销毁定义与给定bean的依赖关系的从属bean。 因此,依赖也可以控制关闭顺序。