1.4. Dependencies

上一节 1.3. Bean Overview

目录

下一节 1.5. Bean Scopes

1.4. Dependencies

1.4. 依赖

A typical enterprise application does not consist of a single object (or bean in the Spring parlance). Even the simplest application has a few objects that work together to present what the end-user sees as a coherent application. This next section explains how you go from defining a number of bean definitions that stand alone to a fully realized application where objects collaborate to achieve a goal.

一个典型的企业级应用不会只包含单个对象(用Spring术语就是bean)。
即使是最简单的应用程序,也有一些对象协同工作,以呈现最终用户视为一致的应用程序。
下一部分将说明你如何从定义好的一系列独立的bean definitions 到各种对象协作达成
某个目的的完整应用程序实现。

[WORD]
1. parlance
英 [ˈpɑːləns]   美 [ˈpɑːrləns]  
n.说法;术语;用语
[W]
1: SPEECH
especially : formal debate or parley
// … battle and not parlance should determine his right and title.【战斗而不是白话应该决定他的权利和头衔。】
— John Speed
2: manner or mode of speech : IDIOM
// The company's computer system had, in computer parlance, "crashed."【用计算机的术语来说,该公司的计算机系统“崩溃了”。】

----
2. coherent
英 [kəʊˈhɪərənt]   美 [koʊˈhɪrənt]  
adj.合乎逻辑的;有条理的;清楚易懂的;有表达能力的;能把自己的意思说清楚的
[W]
1
* a: logically or aesthetically ordered or integrated : CONSISTENT
// coherent style【一致的风格】
// a coherent argument【连贯的论点】
b: having clarity or intelligibility : UNDERSTANDABLE
// a coherent person【有条理的人】
// a coherent passage【连贯的段落】
2: having the quality of holding together or cohering
especially : COHESIVE, COORDINATED
// a coherent plan for action【连贯的行动计划】
3
a: relating to or composed of waves having a constant difference in phase
// coherent light
b: producing coherent light
// a coherent source


1.4.1. Dependency Injection
1.4.1. 依赖注入

Dependency injection (DI) is a process whereby objects define their dependencies (that is, the other objects with which they work) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies on its own by using direct construction of classes or the Service Locator pattern.

依赖注入(DI)对象定义他们的依赖关系的过程(也就是,这个类与其他的类协作),
这个过程只通过构造方法参数,工厂方法参数,或者在它构造或工厂方法生成后
通过set方法设置到对象实例上。
当创建bean的时候,容器注入这些依赖关系。
这个过程与bean自己通过使用类的直接构造方法或者服务器定位模式来控制实例化或者
处理自己的依赖关系完全相反(控制反转,因此得名)。

Code is cleaner with the DI principle, and decoupling is more effective when objects are provided with their dependencies. The object does not look up its dependencies and does not know the location or class of the dependencies. As a result, your classes become easier to test, particularly when the dependencies are on interfaces or abstract base classes, which allow for stub or mock implementations to be used in unit tests.

通过引入依赖注入的概念,代码更简洁,同时当为对象提供依赖时,能够更加有效地去耦。
对象不会查找它的依赖项,也不知道依赖项的位置或者类。因此,您的类变得更容易进行
单元测试,特别是当依赖基于接口或者抽象的基本类,他们允许在单元测试中,使用 
stub或者 mock实现。

DI exists in two major variants: Constructor-based dependency injection and Setter-based dependency injection.

依赖注入存在两种主要的变体:基于构造方法的依赖注入和 基于setter方法的依赖注入。

Constructor-based Dependency Injection

Constructor-based DI is accomplished by the container invoking a constructor with a number of arguments, each representing a dependency. Calling a static factory method with specific arguments to construct the bean is nearly equivalent, and this discussion treats arguments to a constructor and to a static factory method similarly. The following example shows a class that can only be dependency-injected with constructor injection:

基于构造方法的依赖注入是通过容器调用具有多个参数(每个参数代表一个依赖项)的
构造函数来完成的。
调用一个待用特殊参数静态工厂方法来创建bean几乎是一样的,在本次讨论中将构造
函数和静态工厂方法的参数类一样看待。
以下示例显示了只能通过构造函数注入进行依赖项注入的类:



public class SimpleMovieLister {

    // the SimpleMovieLister has a dependency on a MovieFinder
    private MovieFinder movieFinder;

    // a constructor so that the Spring container can inject a MovieFinder
    public SimpleMovieLister(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // business logic that actually uses the injected MovieFinder is omitted...
}

Notice that there is nothing special about this class. It is a POJO that has no dependencies on container specific interfaces, base classes or annotations.

注意,该类没有什么特别的。 它是一个POJO,不依赖于容器特定的接口,基类或注释。


Constructor Argument Resolution

Constructor argument resolution matching occurs by using the argument’s type. If no potential ambiguity exists in the constructor arguments of a bean definition, the order in which the constructor arguments are defined in a bean definition is the order in which those arguments are supplied to the appropriate constructor when the bean is being instantiated. Consider the following class:

构造方法参数解析
构造方法的参数解析的匹配是通过使用参数的类型进行。如果bean definition构造方法的
参数中不存在任何歧义,在实例化Bean时,在Bbean definition定义构造方法参数的顺序
就是将这些参数提供给适当的构造函数的顺序。
考虑下面这个类:


1. resolution
英 [ˌrezəˈluːʃn]   美 [ˌrezəˈluːʃn]  
n.决议;正式决定;(问题、分歧等的)解决,消除;坚定;坚决;有决心
[W]
1: the act or process of resolving: such as
a: the act of analyzing a complex notion into simpler ones
b: the act of answering : SOLVING
c: the act of determining
d: the passing of a voice part from a dissonant to a consonant tone or the progression of a chord from dissonance to consonance
e: the separating of a chemical compound or mixture into its constituents
f(1): the division of a prosodic element into its component parts
(2): the substitution in Greek or Latin prosody of two short syllables for a long syllable
g: the analysis of a vector into two or more vectors of which it is the sum
2: the subsidence of a pathological state (such as inflammation)
3
a: something that is resolved
// made a resolution to mend my ways
b: firmness of resolve
4: a formal expression of opinion, will, or intent voted by an official body or assembled group
5: the point in a literary work at which the chief dramatic complication is worked out
6
a: the process or capability of making distinguishable the individual parts of an object, closely adjacent optical images, or sources of light
b: a measure of the sharpness of an image or of the fineness with which a device (such as a video display, printer, or scanner) can produce or record such an image usually expressed as the total number or density of pixels in the image
// a resolution of 1200 dots per inch

----
2. ambiguity
英 [ˌæmbɪˈɡjuːəti]   美 [ˌæmbɪˈɡjuːəti]  
n.歧义;一语多义;模棱两可的词;含混不清的语句;模棱两可;不明确
[W]
1
a: the quality or state of being ambiguous especially in meaning
// The ambiguity of the poem allows several interpretations.
【这首诗模棱两可允许几种解释。】
b: a word or expression that can be understood in two or more possible ways : an ambiguous word or expression
* 2: UNCERTAINTY




package x.y;

public class ThingOne {

    public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {
        //  ... 
    }
}

Assuming that ThingTwo and ThingThree classes are not related by inheritance, no potential ambiguity exists. Thus, the following configuration works fine, and you do not need to specify the constructor argument indexes or types explicitly in the element.

假设ThingTwo和ThingThree类不是通过继承关联的,也不存在潜在的二义性。
那么,下面的这些配置将很好地工作,并且你不需要你没有必要去显式地在
<constructor-arg/>元素中,为构造方法配置参数索引或者类型。


<beans>
    <bean id="beanOne" class="x.y.ThingOne">
        <constructor-arg ref="beanTwo"/>
        <constructor-arg ref="beanThree"/>
    </bean>

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

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

When another bean is referenced, the type is known, and matching can occur (as was the case with the preceding example). When a simple type is used, such as true, Spring cannot determine the type of the value, and so cannot match by type without help. Consider the following class:

当引用另一个bean时,类型是已知的,并且可以发生匹配(与前面的示例一样)。
当使用简单的类型,例如<value> true </ value>时,Spring无法确定值的类型,
因此在没有帮助的情况下无法按类型进行匹配。
考虑下面这个类:

(也就是说简单类型,必须通过类似 constructor-arg type="int" 来进行显式的指定)


package examples;

public class ExampleBean {

    // Number of years to calculate the Ultimate Answer
    private int years;

    // The Answer to Life, the Universe, and Everything
    private String ultimateAnswer;

    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}
Constructor argument type matching

In the preceding scenario, the container can use type matching with simple types if you explicitly specify the type of the constructor argument by using the type attribute. as the following example shows:

构造方法参数类型匹配
在上述情况下,如果您通过使用type属性明确指定构造函数参数的类型,
则容器可以使用简单类型的类型匹配。
就像下面的例子演示:


<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>
Constructor argument index

You can use the index attribute to specify explicitly the index of constructor arguments, as the following example shows:

构造方法参数索引
你可以使用index属性来明确指定构造方法的参数,就像下面例子演示:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>

In addition to resolving the ambiguity of multiple simple values, specifying an index resolves ambiguity where a constructor has two arguments of the same type.

除了解决多个简单类型参数的二义性之外,指定索引还可以解决构造方法具有两个相同
类型参数的二义性。

The index is 0-based.

index从0开始

Constructor argument name

You can also use the constructor parameter name for value disambiguation, as the following example shows:

构造体参数名称
你同样可以使用构造方法的参数名称来消除歧义,就像下面例子演示:

[WORD]
1. disambiguation
消除歧义;歧义消除;解疑;消歧义;消歧
[W]
: to establish a single semantic or grammatical interpretation forneeded to disambiguate the phrase
【建立必要的单一语义或语法解释以消除歧义】




<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
 </bean>

Keep in mind that, to make this work out of the box, your code must be compiled with the debug flag enabled so that Spring can look up the parameter name from the constructor. If you cannot or do not want to compile your code with the debug flag, you can use the @ConstructorProperties JDK annotation to explicitly name your constructor arguments. The sample class would then have to look as follows:

请记住,要开箱即用地使用该功能,必须在启用调试的情况下编译代码,以便Spring
可以从构造函数中查找参数名称。
如果您不能或者不想启用调试来编译代码,你可以使用@ConstructorProperties 
这个JDK标签来显式地命名您的构造方法参数。
样本类显示如下:


[WORD]
1. out of the box
英 [aʊt ɒv ðə bɒks]   美 [aʊt əv ðə bɑːks]  
开箱即用;即开即用;走出盒子;开包即用;即用的

package examples;

public class ExampleBean {
    // Fields omitted
    @ConstructorProperties({"years", "ultimateAnswer"})
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}
Setter-based Dependency Injection

Setter-based DI is accomplished by the container calling setter methods on your beans after invoking a no-argument constructor or a no-argument static factory method to instantiate your bean.

基于Setter方法的依赖注入
基于Setter方法的依赖注入,通过调用无参数构造方法或无参数静态工厂方法实例化
您的bean之后,在容器上调用bean的setter方法来完成。

The following example shows a class that can only be dependency-injected by using pure setter injection. This class is conventional Java. It is a POJO that has no dependencies on container specific interfaces, base classes, or annotations.

下面的示例显示只能通过使用纯setter注入来进行依赖项注入的类。这个类是常规的Java。
这是一个POJO,不依赖于特定于容器的接口,基类或注释。


[WORD]
1. conventional
英 [kənˈvenʃənl]   美 [kənˈvenʃənl]  
adj.依照惯例的;遵循习俗的;墨守成规的;普通平凡的;传统的;习惯的;非核的;常规的
[W]
1: formed by agreement or compact
2
a: according with, sanctioned by, or based on conventionconventional spellingconventional morality
b: lacking originality or individuality : TRITEMost of her books are conventional detective stories.
c(1): ORDINARY, COMMONPLACEconventional medications
(2): NONNUCLEAR sense 1conventional warfare
3
a: according with a mode of artistic representation that simplifies or provides symbols or substitutes for natural forms
b: of traditional design
4: of, resembling, or relating to a convention, assembly, or public meeting



public class SimpleMovieLister {

    // the SimpleMovieLister has a dependency on the MovieFinder
    private MovieFinder movieFinder;

    // a setter method so that the Spring container can inject a MovieFinder
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // business logic that actually uses the injected MovieFinder is omitted...
}

The ApplicationContext supports constructor-based and setter-based DI for the beans it manages. It also supports setter-based DI after some dependencies have already been injected through the constructor approach. You configure the dependencies in the form of a BeanDefinition, which you use in conjunction with PropertyEditor instances to convert properties from one format to another. However, most Spring users do not work with these classes directly (that is, programmatically) but rather with XML bean definitions, annotated components (that is, classes annotated with @Component, @Controller, and so forth), or @Bean methods in Java-based @Configuration classes. These sources are then converted internally into instances of BeanDefinition and used to load an entire Spring IoC container instance.

ApplicationContext为它管理的bean支持基于构造函数和基于setter方法的依赖注入。
在通过构造方法完成依赖注入后,它还可以通过setter方法完成依赖注入。
您可以以BeanDefinition的形式配置依赖项,将其与PropertyEditor实例结合使用以将
属性从一种格式转换为另一种格式。但是,大多数Spring用户不是直接(即以编程方式)
使用这些类,而是使用XML bean定义,带注释的组件
(即以@ Component,@ Controller注释的类)
或基于Java的@Configuration的@Bean方法 。
这些资源在内部转换为BeanDefinition的实例,并用于加载整个Spring IoC容器实例。


[WORD]
1. conjunction
英 [kənˈdʒʌŋkʃn]   美 [kənˈdʒʌŋkʃn]  
n.连词, 连接词 (如and、but、or);(引起某种结果的事物等的)结合,同时发生;(恒星、行星等的)合
[W]
1: an uninflected linguistic form that joins together sentences, clauses, phrases, or words
// Some common conjunctions are "and," "but," and "although."
2: the act or an instance of conjoining : the state of being conjoined : COMBINATION
// working in conjunction with state and local authorities
3: occurrence together in time or space : CONCURRENCE
// a conjunction of events
4
a: the apparent meeting or passing of two or more celestial bodies in the same degree of the zodiac
b: a configuration in which two celestial bodies have their least apparent separation
// a conjunction of Mars and Jupiter
5: a complex sentence in logic true if and only if each of its components is true
— see TRUTH TABLE



Constructor-based or setter-based DI?

Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. Note that use of the @Required annotation on a setter method can be used to make the property be a required dependency; however, constructor injection with programmatic validation of arguments is preferable.

依赖注入用基于构造函数还是基于setter方法更好?
由于可以混合使用基于构造方法和基于setter方法的依赖注入,因此将构造函数用于
强制性依赖项并将setter方法或配置方法用于可选依赖是一个好的经验法则。
请注意,在setter方法上使用@Required注释可用于使属性成为必需的依赖项; 
但是,最好使用带有参数的程序验证的构造函数注入。

The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.

Spring团队通常提倡构造函数注入,因为它可以让您将应用程序组件实现为不可变对象,
并确保所需的依赖项不为空。
此外,注入构造函数的组件始终以完全初始化的状态返回给客户端(调用)代码。
附带说明一下,构造方法包含太多的自变量是一种不好的编码习惯,这意味着该类可能
承担了太多的职责,应进行重构以更好地解决关注点分离问题。
(这里的动词address怎么理解?)

[WORD]
1. advocates
英 [ˈædvəkeɪts]   美 [ˈædvəkeɪts]  
v.拥护;支持;提倡
n.拥护者;支持者;提倡者;辩护律师;出庭辩护人
advocate的第三人称单数和复数
[W]
1: one who pleads the cause of anotherspecifically : one who pleads the cause of another before a tribunal or judicial court
2: one who defends or maintains a cause or proposal
// an advocate of liberal arts education
3: one who supports or promotes the interests of a cause or group
// a consumer advocate
// an advocate for women's health
// He has paid respectful attention to the home schooling movement by meeting with its advocates and endorsing their cause.
— Elizabeth Drew


Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.

Setter方法的注入主要应仅用于可以在类中分配合理的默认值的可选依赖项。
否则,必须在代码使用依赖项的每一个地方都执行非空检查。
setter方法注入的一个优势是,setter方法使这个类的对象在以后可以重新配置或重新注入。
因此,通过JMX MBeans进行管理是setter方法注入的引人注目的用例。

[WORD]
1. amenable
英 [əˈmiːnəbl]   美 [əˈmiːnəbl]  
adj.顺从的;顺服的;可用某种方式处理的
[W]
1: liable to be brought to account : ANSWERABLE
// citizens amenable to the law【服从法律的公民】
2
* a: capable of submission (as to judgment or test) : SUITED
// The data is amenable to analysis.【数据适合分析。】
b: readily brought to yield, submit, or cooperate
// a government not amenable to change【不宜改变的政府】
c: WILLING sense 1
// was amenable to spending more time at home 【可以花更多的时间在家里】

----
2. compelling
英 [kəmˈpelɪŋ]   美 [kəmˈpelɪŋ]  
adj.引人入胜的;扣人心弦的;非常强烈的;不可抗拒的;令人信服的
v.强迫;迫使;使必须;引起(反应)
compel的现在分词
[W]
a: FORCEFUL
// a compelling personality【令人信服的人格】
// a compelling desire【令人信服的欲望】
b: demanding attention
// for compelling reasons【令人信服的理由】
// The novel was so compelling that I couldn't put it down.【这本小说太引人注目了,以至于我不能拒绝它。】
c: CONVINCING
// no compelling evidence【没有令人信服的证据】



Use the DI style that makes the most sense for a particular class. Sometimes, when dealing with third-party classes for which you do not have the source, the choice is made for you. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI.

使用依赖注入方式对某一些特定的类是很有意义的。有时候,当使用没提供源代码的
第三方类的时候,你没有其他的选择。
例如,如果第三方类未公开任何setter方法,则构造方法注入可能是依赖注入的唯一可用形式。
 
Dependency Resolution Process

The container performs bean dependency resolution as follows:

  • The ApplicationContext is created and initialized with configuration metadata that describes all the beans. Configuration metadata can be specified by XML, Java code, or annotations.
  • For each bean, its dependencies are expressed in the form of properties, constructor arguments, or arguments to the static-factory method (if you use that instead of a normal constructor). These dependencies are provided to the bean, when the bean is actually created.
  • Each property or constructor argument is an actual definition of the value to set, or a reference to another bean in the container.
  • Each property or constructor argument that is a value is converted from its specified format to the actual type of that property or constructor argument. By default, Spring can convert a value supplied in string format to all built-in types, such as int, long, String, boolean, and so forth.
处理依赖的过程
容器处理bean依赖的过程如下所示:
* 通过描述所有bean的配置元数据来创建和初始化ApplicationContext。
配置元数据可以使用XML、Java代码或者标签形式。
* 对于每个bean,其依赖项都以属性,构造方法的参数或静态工厂方法的参数的形式来表示
 (如果使用它而不是普通的构造方法)。
  当实际创建Bean的时候,会将这些依赖项提供给Bean。
* 每个属性或构造方法的参数都是需要被设置的实际定义值,或者是在容器中对另一个
  bean的引用。
* 每个属性或构造方法的参数都是一个值,它从一个特定的格式转换为属性和构造方法
  参数的实际类型。
默认情况下,Spring可以将以字符串格式提供的值转换为所有内置类型,
例如int,long,String,boolean等。


The Spring container validates the configuration of each bean as the container is created. However, the bean properties themselves are not set until the bean is actually created. Beans that are singleton-scoped and set to be pre-instantiated (the default) are created when the container is created. Scopes are defined in Bean Scopes. Otherwise, the bean is created only when it is requested. Creation of a bean potentially causes a graph of beans to be created, as the bean’s dependencies and its dependencies’ dependencies (and so on) are created and assigned. Note that resolution mismatches among those dependencies may show up late — that is, on first creation of the affected bean.

Spring容器在创建的时候会验证每一个bean配置的有效性。
但是,bean内部的属性值一直到bean被实际创建的时候才会设置。
当创建容器的时候,singleton类型的bean和设置为预先实例化(默认)的Bean会被创建。
Scopes 被定义在bean的Scopes属性上。
否则,bean仅仅在被调用的时候被创建。
创建和分配Bean的依赖关系及其依赖的依赖关系(依此类推)时,Bean的创建可能会
导致一个Bean的创建集合。
请注意,这些依赖关系之间的不匹配可能会在后期出现,即在首次创建受影响的bean时。

Circular dependencies

If you use predominantly constructor injection, it is possible to create an unresolvable circular dependency scenario.

循环依赖
如果您主要使用构造方法注入,可能会产生一个不可解决的循环依赖情况。

[WORD]
1. predominantly
英 [prɪˈdɒmɪnəntli]   美 [prɪˈdɑːmɪnəntli]  
adv.主要地;多数情况下

For example: Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException.

例如:Class A通过构造方法注入依赖于 Class B,同时 Class B通过构造方法注入
依赖于 Class A。如果您配置A和B两个类都注入到对方的bean,
Spring IoC容器在运行时检测到这种循环引用,就可能抛出
BeanCurrentlyInCreationException 异常。


One possible solution is to edit the source code of some classes to be configured by setters rather than constructors. Alternatively, avoid constructor injection and use setter injection only. In other words, although it is not recommended, you can configure circular dependencies with setter injection.

一个可行的解决办法就是改变某些类的源代码,把构造方法配置为setter方法。
或者,避免使用构造方法注入,而只使用setter方法注入。
换句话说,尽管不建议这样做,但是您可以使用setter方法注入配置循环依赖关系。

Unlike the typical case (with no circular dependencies), a circular dependency between bean A and bean B forces one of the beans to be injected into the other prior to being fully initialized itself (a classic chicken-and-egg scenario).

与典型的情况(没有循环依赖关系)不同,Bean A和Bean B之间的循环依赖关系迫使
其中一个Bean在完全初始化之前被注入另一个Bean(经典的“鸡与蛋”问题)。

You can generally trust Spring to do the right thing. It detects configuration problems, such as references to non-existent beans and circular dependencies, at container load-time. Spring sets properties and resolves dependencies as late as possible, when the bean is actually created. This means that a Spring container that has loaded correctly can later generate an exception when you request an object if there is a problem creating that object or one of its dependencies — for example, the bean throws an exception as a result of a missing or invalid property. This potentially delayed visibility of some configuration issues is why ApplicationContext implementations by default pre-instantiate singleton beans. At the cost of some upfront time and memory to create these beans before they are actually needed, you discover configuration issues when the ApplicationContext is created, not later. You can still override this default behavior so that singleton beans initialize lazily, rather than being pre-instantiated.

通常,您可以信任Spring去做正确的事。它在容器加载时检测配置方面的问题,
例如对不存在的Bean的引用和循环依赖。
在实际创建Bean时,Spring尽可能晚地设置属性并解决依赖关系。
这意味着,在Spring的容器正确加载后,如果创建对象或其依赖关系有问题的话,
可以在您请求对象的时候生成异常-例如,由于缺少属性或属性无效,Bean抛出异常。
这也就是为什么默认情况下ApplicationContext的实现会预先实例化Singleton Bean,
来避免某些配置问题的这种潜在的延迟可见性。
在你预先花费CPU时间和内存资源创建beans实际需要bean之前,当
ApplicationContext被创建的时候,你发现配置问题(而不是之后)。
您也可以覆盖此默认方法,以便singleton bean延迟初始化,而不是预先实例化。

[WORD]
1. upfront
英 [ˌʌpˈfrʌnt]   美 [ˌʌpˈfrʌnt]  
adj.坦率的;诚实的;直爽的;预付的;预交的
[W]
a
(1): FRANK, FORTHRIGHT
(2): being in a conspicuous or leading position
b: paid or payable in advance
c: playing in a front line (as in football)


If no circular dependencies exist, when one or more collaborating beans are being injected into a dependent bean, each collaborating bean is totally configured prior to being injected into the dependent bean. This means that, if bean A has a dependency on bean B, the Spring IoC container completely configures bean B prior to invoking the setter method on bean A. In other words, the bean is instantiated (if it is not a pre-instantiated singleton), its dependencies are set, and the relevant lifecycle methods (such as a configured init method or the InitializingBean callback method) are invoked.

如果不存在循环依赖,则在将一个或多个协作Bean注入到被依赖的Bean中时,
每个协作Bean都将被完全配置,然后再注入到被依赖的Bean中。
也就是说,如果bean A依赖bean B ,那么Spring IoC容器会在bean A调用setter方法
之前,完全配置bean B。
换句话说,bean被实例化(如果它不是预先实例化的singleton类型),
它的依赖关系被设置,并且相关的生命周期方法被调用。
(例如配置的init方法或InitializingBean回调方法)。


Examples of Dependency Injection

The following example uses XML-based configuration metadata for setter-based DI. A small part of a Spring XML configuration file specifies some bean definitions as follows:

依赖注入的例子
下面的例子使用基于XML的配置元数据作为setter方法的依赖注入。
Spring关于 bean definitions的XML配置文件代码片段如下:

<bean id="exampleBean" class="examples.ExampleBean">
    <!-- setter injection using the nested ref element -->
    <property name="beanOne">
        <ref bean="anotherExampleBean"/>
    </property>

    <!-- setter injection using the neater ref attribute -->
    <property name="beanTwo" ref="yetAnotherBean"/>
    <property name="integerProperty" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

The following example shows the corresponding ExampleBean class:

下面的例子显示了相关联的ExampleBean 类。


public class ExampleBean {

    private AnotherBean beanOne;

    private YetAnotherBean beanTwo;

    private int i;

    public void setBeanOne(AnotherBean beanOne) {
        this.beanOne = beanOne;
    }

    public void setBeanTwo(YetAnotherBean beanTwo) {
        this.beanTwo = beanTwo;
    }

    public void setIntegerProperty(int i) {
        this.i = i;
    }
}

In the preceding example, setters are declared to match against the properties specified in the XML file. The following example uses constructor-based DI:

在上面的例子中,几个setter方法与XML文件中的属性匹配。
下面的例子是基于构造方法的依赖注入:

<bean id="exampleBean" class="examples.ExampleBean">
    <!-- constructor injection using the nested ref element -->
    <constructor-arg>
        <ref bean="anotherExampleBean"/>
    </constructor-arg>

    <!-- constructor injection using the neater ref attribute -->
    <constructor-arg ref="yetAnotherBean"/>

    <constructor-arg type="int" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

The following example shows the corresponding ExampleBean class:

下面的案例占式相关联的 ExampleBean 类


public class ExampleBean {
    private AnotherBean beanOne;
    private YetAnotherBean beanTwo;
    private int i;

    public ExampleBean(
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
        this.beanOne = anotherBean;
        this.beanTwo = yetAnotherBean;
        this.i = i;
    }
}

The constructor arguments specified in the bean definition are used as arguments to the constructor of the ExampleBean.

 bean definition中的 构造方法参数 ,作为参数设置到 ExampleBean的构造方法。

Now consider a variant of this example, where, instead of using a constructor, Spring is told to call a static factory method to return an instance of the object:

现在看一下这个例子的变体,这里不使用构造方法,Spring调用静态工厂方法返回对象的实例。

<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance">
    <constructor-arg ref="anotherExampleBean"/>
    <constructor-arg ref="yetAnotherBean"/>
    <constructor-arg value="1"/></bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

The following example shows the corresponding ExampleBean class:

下面的例子显示了相关联的ExampleBean 类。

public class ExampleBean {

    // a private constructor
    private ExampleBean(...) {
        ...
    }

    // a static factory method; the arguments to this method can be
    // considered the dependencies of the bean that is returned,
    // regardless of how those arguments are actually used.
    public static ExampleBean createInstance (
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {

        ExampleBean eb = new ExampleBean (...);
        // some other operations...
        return eb;
    }
}

Arguments to the static factory method are supplied by elements, exactly the same as if a constructor had actually been used. The type of the class being returned by the factory method does not have to be of the same type as the class that contains the static factory method (although, in this example, it is). An instance (non-static) factory method can be used in an essentially identical fashion (aside from the use of the factory-bean attribute instead of the class attribute), so we do not discuss those details here.

静态工厂方法的参数设置在  <constructor-arg/>  元素下,类似于 构造方法被实际使用的情况。
工厂方法返回的类的类型不必与包含静态工厂方法的类的类型相同(尽管在这个示例中是相同的)。
实例工厂方法(非静态)可以以基本上相同的方式使用
(不是通过Class属性,而是使用factory-bean属性),
因此在此不讨论这些细节。


1.4.2. Dependencies and Configuration in Detail
1.4.2. 详解依赖和配置

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属性和构造方法参数定义为对其他被管理的bean(协作者)
的引用或内联定义的值。
Spring基于XML的配置元数据通过<property/> and <constructor-arg/>中的子节点
类型来支持这个特性。
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 shows various values being set:

直接的值(基本类型、字符串等)
<property/>元素的值属性把属性或者构造方法参数表示为人类可读的字符串形式。
Spring的转换服务将这些值从字符串转换为属性或参数的实际类型。
下面的例子现实了不同的值的设置:

[WORD]
1. Primitives
英 [ˈprɪmɪtɪvz]   美 [ˈprɪmətɪvz]  
基本体;基本实体;基本体素;原语;原始几何体
[W]
1a: not derived : ORIGINAL, PRIMARY
b: assumed as a basis
especially : AXIOMATIC
// primitive concepts
2
a: of or relating to the earliest age or period : PRIMEVAL
// the primitive church
b: closely approximating an early ancestral type : little evolved
// primitive mammals
c: belonging to or characteristic of an early stage of development : CRUDE, RUDIMENTARY
primitive technology
d: of, relating to, or constituting the assumed parent speech of related languages
// primitive Germanic
3a: ELEMENTAL, NATURAL
// our primitive feelings of vengeance
— John Mackwood
bnow sometimes offensive : of, relating to, or produced by a people or culture that is nonindustrial and often nonliterate and tribal
// primitive art
c: NAIVE
d(1): SELF-TAUGHT, UNTUTORED
// primitive craftsmen
(2): produced by a self-taught artist
// a primitive painting


<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="masterkaoli"/>
</bean>

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

下面例子使用p-namespace这种更加简洁的XML配置方式:

<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="masterkaoli"/>

</beans>

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.

以上的XML更加简洁。
但是,除非在创建bean定义时使用支持自动属性完成的IDE
(例如IntelliJ IDEA或Eclipse的Spring Tools),否则语法错误是在运行时而不是设计时发现的。
我们极力推荐这类型的IDE辅助工具。

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

你也可以通过下面的方式,配置 java.util.Properties 实例。

<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>

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机制将<value />元素内的文本转换为
java.util.Properties实例。
这是一个不错的捷径,并且是Spring团队偏爱使用嵌套的<value />元素而不是value
属性样式的几个地方之一。
(one of a few places 怎么理解,除了这里,还有哪些地方)

The idref element

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 or element. The following example shows how to use it:

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


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

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

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

前面的bean定义代码段(在运行时)与以下代码段完全等效:

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

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

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标记可以使容器在部署阶段就验证所引用的
命名bean实际存在。
在第二个例子中,传递到客户端bean的targetName属性的值不会执行验证。
如果拼写错误仅在实际实例化客户bean时才发现(最有可能导致致命的结果)。
如果客户端bean是 prototype 类型的bean,则可能在部署容器很长时间之后才发现
此错字和所产生的异常。
(这个很好理解,因为prototype类型的bean,只有在request才会被实例化)

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.

4.0版本Bean XSD不再支持idref元素上的local属性,因为它不再提供常规Bean引用上的值。
如果您升级到4.0的schema,记得改变您存量的idref本地引用为idref 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.

<idref />元素带来的一个常见有价值的地方(至少在Spring 2.0之前的版本中)
是在ProxyFactoryBean 的bean definition中AOP拦截器的配置。
指定拦截器名称时使用<idref />元素可防止您拼写错误的拦截器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 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.

对其他Bean的引用(协作者)
ref元素是<constructor-arg />或<property />定义元素内的最后一个元素。
在这里,您将bean的指定属性的值设置为对容器管理的另一个bean(协作者)的引用。
被引用的bean是属性被设置的bean的依赖,在设置属性之前根据需要对其进行初始化。
(如果协作者是singleton类型的bean,那么它可能已经被容器初始化过了)
所有引用最终都是对另一个对象的引用。应用范围和有效性取决于你是通过另外一个
对象的id或名称,还是parent属性来创建bean。


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 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是最通用的形式,无论是否在同一XML文件中定义,
都允许创建对同一容器或父容器中任何bean的引用。
bean属性的值应该与目标bean的id属性或者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的引用。
parent属性的值可以与目标Bean的id属性或目标Bean的name属性中的值其中之一相同。
目标bean必须在当前容器的父容器中。
当你在具有容器层次结构并且代理方法中声明与父bean相同名称的bean时候,
你可能使用到这种bean引用变量
下面这一对XML文件展示了如何使用 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.0版本Bean XSD不再支持idref元素上的local属性,因为它不再提供常规Bean引用上的值。
如果您升级到4.0的schema,
记得改变您存量的idref本地引用为idref bean。

Inner Beans

A element inside the or elements defines an inner bean, as the following example shows:

内部bean
在<property/> 或者 <constructor-arg/> 标签下面的 <bean/>标签定义了一个内部bean,
看一下下面这个例子:

<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 definition不需要一个定义的ID或者name。如果指定value,
容器不使用这个value作为标识符。
同时,容器也会在创建的时候忽略scope作用域,因为内部类通常都是匿名的,
并且随着外部的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.

作为一个特例,可以从自定义作用域中接收销毁回调,例如request scope类型的
内部类在singleton类的bean的情况。
内部bean实例的创建与包含它的bean绑定在一起,但是销毁回调使它可以参与
request scope的生命周期。
这不是常见的情况。 内部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的各类Collection类型
List, Set, Map, and 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

map类型的key或者value,set类型的value,可以是以下这些元素:
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 , , or element and have child , , 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.

Collection的合并
Spring容器也支持合并Collection。应用程序的开发者可以定义父节点 
<list/>, <map/>, <set/> or <props/> ,也可以设置子节点
<list/>, <map/>, <set/> or <props/>,继承或者重载父collection的值。
也就是说,子collection的值 是合并了父和子collections的元素,
子collection元素重载了父collection的值。

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定义的读者可能希望先阅读相关部分,然后再继续。

The following example demonstrates collection merging:

下面的例子演示了collection的合并。

<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 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 definition的adminEmails属性的<props />元素上使用
merge = true属性。
当子bean由容器解析并实例化的时候,生成的实例具有adminEmails Properties集合,
其中包含将子bean 的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 , and the child’s value for the support value overrides the value in the parent collection.

子“属性”集合的值集继承了父<props />的所有属性元素,并且子项相同名称的值
覆盖了父集合中的值。

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.

<list/>, <map/>, and <set/>等集合类型的合并过程类似。
在<list />元素这个特例下,将维护与List集合类型关联的语义
(即,值的有序集合的概念)。父级的值先于子级列表的所有值 。
在Map, Set, and Properties这类集合类型中,不存在排序问题。
因此,对于容器内部使用的关联Map,Set和Properties实现类型基础的集合类型,
没有任何排序语义有效。


1. underlie
英 [ˌʌndəˈlaɪ]   美 [ˌʌndərˈlaɪ]  
v.构成…的基础;作为…的原因
[W]
1: to lie or be situated under
2: to be at the basis of : form the foundation of : SUPPORT
// ideas underlying the revolution【革命的思想基础】
3: to exist as a claim or security superior and prior to (another)
4 archaic : to be subject or amenable to



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.

集合合并的限制
你不能合并不同类型的集合(例如把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 (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 5中通用类型的引入,您可以使用强类型集合。
也就是说,可以声明一个Collection类型,使其只包含(例如)String元素。
如果使用Spring将强类型的Collection依赖注入到Bean中,则可以利用Spring的类型转换支持,
以便在将强类型的Collection实例的元素添加到Bean中之前,先将其转换为适当的类型。
下面的Java类和bean definition显示了如何做到这一点:

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.

当准备注入某个bean的accounts属性时,可以通过反射获得有关强类型
Map <String,Float>的元素类型的泛型信息。
因此,Spring的类型转换模块将各元素的值识别为Float类型,并将字符串值
(9.99、2.75和3.99)转换为实际的Float类型。

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 ("").

Null和空字符串的值
Spring把属性等的空参数视为空String。下面基于XML的配置元数据代码片段把
email属性设置为空字符串值""。


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

The preceding example is equivalent to the following Java code:

上面的例子与下面的Java代码一样。

exampleBean.setEmail("");

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

 <null/>元素处理null值,下面演示这个案例:

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

The preceding configuration is equivalent to the following Java code:

上面的配置与下面的Java代码一致。

exampleBean.setEmail(null);
XML Shortcut with the p-namespace

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

使用P-命名空间的XML便捷标签
通过p-namespace标签,您可以使用bean元素的属性(而不是嵌套的<property />元素)
来描述协作bean的属性值,或同时使用这两者。
(or both 是指哪两个?

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支持带有名称空间的可扩展配置格式,这些名称空间基于XML Schema定义。
本章讨论的bean配置格式在XML Schema文档中定义。
但是,p命名空间未在XSD文件中定义,仅存在于Spring的核心中。
(这就是为什么idea里面要对 p命名空间进行设置,否则XML会报错)

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:

下面的例子演示了两个XML片段(第一个使用标准的XML格式,第二个使用p命名空间),
他们可以解决同样的问题。

<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>

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.

该示例在p命名空间中的bean definition中显示了一个名为email的属性。
它告诉Spring包含一个属性声明。
如前所述,p名称空间没有架构定义,因此您可以将property 名称设置为attribute 名称。

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

下面的例子包含了两个 bean definitions,他们都引用另外一个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>

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-namespace的属性值,而且还使用特殊格式来声明属性引用。
第一个bean definition使用<property name= spouse” ref= jane” />
创建从bean john到bean jane的引用,
而第二个bean definition使用p:spouse-ref= jane”作为属性来完成相同的操作。
在这个案例中,spouse是属性名称,而-ref部分表示这不是一个直接值,
而是对另一个bean的引用。

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.

p命名空间不像标准的XML格式那样灵活。
例如,声明属性引用的格式可能与以Ref结尾的属性冲突,而标准XML格式不存在这个问题。
我们建议您仔细选择您的方法,并将这些情况与团队成员沟通,以避免同时使用这三种方法
生成XML文档。
(这里的三种方法是哪三种?)

XML Shortcut with the c-namespace

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-命名空间的XML便捷标签
与P-命名空间的XML便捷标签类似,Spring3.1引入了c-命名空间,
它允许使用内联属性来配置构造方法参数,而不是嵌套的builder-arg元素。

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

下面的案例使用 c-命名空间来完成 基于构造方法依赖注入相同的功能:

<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>

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).

c:命名空间使用与p:命名空间相同的约定方式(bean引用为尾随-ref)
以按名称设置构造函数参数。 
同样,因为在XSD schema中没有定义(也存在于Spring内核中),
所以需要在XML文件中声明它。

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"/>

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 elements but not commonly used since the plain order of declaration is usually sufficient there.

由于XML语法的原因,索引符号要求以_开头,因为XML属性名称不能以数字开头
(即使某些IDE允许)。
相应的索引符号也可用于<constructor-arg>元素,但并不常用,因为声明直接的顺序就足够了。


In practice, the constructor resolution mechanism is quite efficient in matching arguments, so unless you really need 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属性时,可以使用复合属性名称或嵌套属性名称,只要路径中除最终属性名称
之外的所有组件都不为空即可。
让我们看一下下面的bean definition:

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

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.

something这个bean有一个 fred属性,该属性有bob属性,bob属性下面有sammy属性,
最终的sammy属性值为123.
为了使它起作用,在构造bean之后,something的fred属性和fred的bob属性一定不能为null。 
否则,将引发NullPointerException异常。

1.4.3. 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:

1.4.3. 使用 depends-on标签
如果一个bean是另外一个bean的依赖项,通常意味着这个bean被作为属性设置给另外这个bean。
通常,您可以使用基于XML的配置元数据中的<ref />元素来完成此操作。
但是,有时bean之间的依赖性不太直接。一个案例是何时需要触发类中的静态初始化方法,
例如数据库驱动程序的注册。
下面的例子中使用depends-on属性来生成单个bean的依赖关系。

<bean id="beanOne" class="ExampleBean" depends-on="manager"/>
<bean id="manager" class="ManagerBean" />

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-on 属性上提供一个bean名称的清单作为值
(逗号,空格和分号都是有效的间隔符)。

<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
    <property name="manager" ref="manager" />
</bean>

<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />

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属性 既可以指定初始化时间的依赖,也可以指定相应的销毁时间的依赖
(只限于singleton类型bean)。
与给定bean的依赖关系的从属bean首先被销毁,然后再销毁给定bean本身。
这样depends-on可以控制关闭的顺序。


1.4.4. Lazy-initialized Beans

By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process. Generally, this pre-instantiation is desirable, because errors in the configuration or surrounding environment are discovered immediately, as opposed to hours or even days later. When this behavior is not desirable, you can prevent pre-instantiation of a singleton bean by marking the bean definition as being lazy-initialized. A lazy-initialized bean tells the IoC container to create a bean instance when it is first requested, rather than at startup.

1.4.4. 延迟初始化的bean
默认情况下,ApplicationContext的实现类在初始化过程中,主动地创建和配置
所有single类型的bean。
通常,这种预初始化的做法非常可取,因为快速地发现配置和环境的错误,
要好过几小时甚至几天后发现这些问题。
当不值得这么做的时候,你可以通过标记bean definition lazy-initialized的方式
阻止某个single类型的bean的预初始化。
 lazy-initialized类型的bean告诉IoC容器,在第一次被请求的时候,创建这个bean。

1. desirable
英 [dɪˈzaɪərəbl]   美 [dɪˈzaɪərəbl]  
adj.向往的;可取的;值得拥有的;值得做的;引起性欲的;性感的
n.称心如意的人[东西]
[W]
1: having pleasing qualities or properties : ATTRACTIVE"
// Mr. Darcy, you must allow me to present this young lady to you as a very desirable partner."
— Jane Austen
// a house in a highly desirable location
2: worth seeking or doing as advantageous, beneficial, or wise : ADVISABLE
// desirable legislation




In XML, this behavior is controlled by the lazy-init attribute on the element, as the following example shows:

在XML中,此设置由<bean />元素上的lazy-init属性控制,如以下示例所示:

<bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/>
<bean name="not.lazy" class="com.something.AnotherBean"/>

When the preceding configuration is consumed by an ApplicationContext, the lazy bean is not eagerly pre-instantiated when the ApplicationContext starts, whereas the not.lazy bean is eagerly pre-instantiated.

当ApplicationContext使用了上面配置的时候,ApplicationContext启动时
不会急于预先实例化 lazy这个 bean,而not.lazy 这个Bean则会预先实例化。

However, when a lazy-initialized bean is a dependency of a singleton bean that is not lazy-initialized, the ApplicationContext creates the lazy-initialized bean at startup, because it must satisfy the singleton’s dependencies. The lazy-initialized bean is injected into a singleton bean elsewhere that is not lazy-initialized.

另外,如果延迟初始化的bean是未延迟初始化的singleton类bean的依赖项,
则ApplicationContext在启动时会创建延迟初始化的bean,因为它必须满足
singleton bean的依赖项。
延迟初始化的bean被注入到其他未延迟初始化的singleton类bean中。


You can also control lazy-initialization at the container level by using the default-lazy-init attribute on the element, a the following example shows:

通过在<beans/>标签上配置  default-lazy-init属性,你可以在容器级别上控制延迟实例化,
就像下面代码演示的这样:

<beans default-lazy-init="true">
    <!-- no beans will be pre-instantiated... --></beans>
1.4.5. Autowiring Collaborators

The Spring container can autowire relationships between collaborating beans. You can let Spring resolve collaborators (other beans) automatically for your bean by inspecting the contents of the ApplicationContext. Autowiring has the following advantages:

1.4.5. 自动装配的合作者
Spring容器可以自动连接协作bean之间的关系。您可以通过检查ApplicationContext的内容,
让Spring为您的bean自动解析协作者(其他bean)。
自动装配有以下优点:

  • Autowiring can significantly reduce the need to specify properties or constructor arguments. (Other mechanisms such as a bean template discussed elsewhere in this chapter are also valuable in this regard.)
  • Autowiring can update a configuration as your objects evolve. For example, if you need to add a dependency to a class, that dependency can be satisfied automatically without you needing to modify the configuration. Thus autowiring can be especially useful during development, without negating the option of switching to explicit wiring when the code base becomes more stable.
* 自动装配可以显著减少指定属性或构造函数参数的需要。
(在这方面,本章其他地方讨论的bean模板等其他机制也很有价值。)
* 自动装配可以随着对象的发展更新配置。
例如,如果需要向类添加依赖项,则无需修改配置即可自动满足该依赖项。
因此,自动装配在开发过程中特别有用,当代码库变得更加稳定时,无需切换到显式连接。

[WORD]
negating
v. 取消;(使)无效;否定(从句、命题);否认(某物)(negate 的现在分词)

When using XML-based configuration metadata (see Dependency Injection), you can specify the autowire mode for a bean definition with the autowire attribute of the element. The autowiring functionality has four modes. You specify autowiring per bean and can thus choose which ones to autowire. The following table describes the four autowiring modes:

当使用基于xml的配置元数据(参见依赖项注入)时,您可以使用<bean/>元素的
autowire属性为bean定义指定自动连接模式。
自动装配功能有四种模式。您可以为每个bean指定自动装配,因此可以选择要
自动装配的bean。
下表介绍了四种自动装配模式:

Table 2. Autowiring modes
ModeExplanation
no(Default) No autowiring. Bean references must be defined by ref elements. Changing the default setting is not recommended for larger deployments, because specifying collaborators explicitly gives greater control and clarity. To some extent, it documents the structure of a system.
byNameAutowiring by property name. Spring looks for a bean with the same name as the property that needs to be autowired. For example, if a bean definition is set to autowire by name and it contains a master property (that is, it has a setMaster(…) method), Spring looks for a bean definition named master and uses it to set the property.
byTypeLets a property be autowired if exactly one bean of the property type exists in the container. If more than one exists, a fatal exception is thrown, which indicates that you may not use byType autowiring for that bean. If there are no matching beans, nothing happens (the property is not set).
constructorAnalogous to byType but applies to constructor arguments. If there is not exactly one bean of the constructor argument type in the container, a fatal error is raised.
no:没有自动装配。Bean引用必须由ref元素定义。对于较大的部署,
不建议更改默认设置,因为显式地指定collaborator可以提供更好的控制和清晰度。
在某种程度上,它记录了系统的结构。
byName:按属性名称自动装配。Spring寻找与需要自动实现的属性同名的bean。
例如,如果一个bean定义按名称设置为autowire,并且它包含一个master属性
(也就是说,它有一个setMaster(..)方法),那么Spring将查找一个名为master的bean定义,
并使用它来设置该属性。
byType:如果容器中恰好存在该属性类型的一个bean,则允许该属性自动实现。
如果存在多个,就会抛出一个致命异常,这表明您不能对该bean使用byType自动装配。
如果没有匹配的bean,则什么也不会发生(没有设置属性)。
constructor:如果容器中没有构造函数参数类型的确切bean,就会引发致命错误。


With byType or constructor autowiring mode, you can wire arrays and typed collections. In such cases, all autowire candidates within the container that match the expected type are provided to satisfy the dependency. You can autowire strongly-typed Map instances if the expected key type is String. An autowired Map instance’s values consist of all bean instances that match the expected type, and the Map instance’s keys contain the corresponding bean names.

使用byType或构造函数自动装配模式,您可以连接数组和类型化集合。
在这种情况下,提供容器中与预期类型匹配的所有自动装配候选对象来满足依赖关系。
如果期望的键类型是String,您可以自动连接强类型Map实例。
自动生成的Map实例的值由与预期类型匹配的所有bean实例组成,
Map实例的键包含相应的bean名称。


Limitations and Disadvantages of Autowiring

Autowiring works best when it is used consistently across a project. If autowiring is not used in general, it might be confusing to developers to use it to wire only one or two bean definitions.

自动装配的局限性和缺点
自动装配在项目中一致使用时工作得最好。如果自动装配没有被普遍使用,
那么使用它来连接一个或两个bean定义可能会使开发人员感到困惑。

Consider the limitations and disadvantages of autowiring:

考虑自动装配的局限性和缺点:

  • Explicit dependencies in property and constructor-arg settings always override autowiring. You cannot autowire simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). This limitation is by-design.
  • Autowiring is less exact than explicit wiring. Although, as noted in the earlier table, Spring is careful to avoid guessing in case of ambiguity that might have unexpected results. The relationships between your Spring-managed objects are no longer documented explicitly.
  • Wiring information may not be available to tools that may generate documentation from a Spring container.
  • Multiple bean definitions within the container may match the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or Map instances, this is not necessarily a problem. However, for dependencies that expect a single value, this ambiguity is not arbitrarily resolved. If no unique bean definition is available, an exception is thrown.
* 属性和构造参数设置中的显式依赖关系总是覆盖自动装配。
您不能自动连接简单属性,如基本类型、字符串和类(以及此类简单属性的数组)。
这种限制是设计出来的。
* 自动装配不如显式连接精确。
  不过,正如前面的表中所指出的,Spring小心地避免猜测可能会产生意外结果的歧义。
  spring管理对象之间的关系不再被明确地记录。
* 连接信息可能对可能从Spring容器生成文档的工具无效。
* 容器中的多个bean definition 可能与要自动实现的setter方法或构造函数参数指定的
类型相匹配。
对于数组、集合或Map实例,这不一定是个问题。但是,对于期望使用单个值的依赖项,
这种模糊性不能任意解决。如果没有可用的惟一bean定义,则抛出异常。

In the latter scenario, you have several options:

  • Abandon autowiring in favor of explicit wiring.
  • Avoid autowiring for a bean definition by setting its autowire-candidate attributes to false, as described in the next section.
  • Designate a single bean definition as the primary candidate by setting the primary attribute of its element to true.
  • Implement the more fine-grained control available with annotation-based configuration, as described in Annotation-based Container Configuration.
在后一种情况下,您有几个选项:
* 放弃自动装配,采用显式连接。
* 通过将一个bean定义的autowire-candidate属性设置为false来避免自动装配,
  如 下一节所述。
* 通过将单个bean定义的<bean/>元素的primary设置为true,
  将其指定为主候选bean定义。
* 使用基于注释的配置实现更细粒度的控制,如在基于注释的容器配置中所描述的那样。

Excluding a Bean from Autowiring

On a per-bean basis, you can exclude a bean from autowiring. In Spring’s XML format, set the autowire-candidate attribute of the element to false. The container makes that specific bean definition unavailable to the autowiring infrastructure (including annotation style configurations such as @Autowired).

排除自动装配bean
在每个bean的基础上,您可以从自动装配中排除一个bean。
在Spring的XML格式中,将<bean/>元素的autowire-candidate属性设置为false。
容器使那个特定的bean definition对自动装配不可用。
(包括注释风格配置,比如@Autowired)

The autowire-candidate attribute is designed to only affect type-based autowiring. It does not affect explicit references by name, which get resolved even if the specified bean is not marked as an autowire candidate. As a consequence, autowiring by name nevertheless injects a bean if the name matches.

autowire-candidate属性被设计为只影响基于类型的自动装配。
它不影响按名称的显式引用,即使指定的bean没有标记为自动装配候选,
也会解析显式引用。
因此,如果名称匹配,按名称自动装配仍然会注入一个bean。


You can also limit autowire candidates based on pattern-matching against bean names. The top-level element accepts one or more patterns within its default-autowire-candidates attribute. For example, to limit autowire candidate status to any bean whose name ends with Repository, provide a value of * Repository. To provide multiple patterns, define them in a comma-separated list. An explicit value of true or false for a bean definition’s autowire-candidate attribute always takes precedence. For such beans, the pattern matching rules do not apply.

您还可以基于对bean名称的模式匹配来限制自动连接候选项。
顶级的<beans/>元素在其default-autowire-candidates属性中接受一个或多个模式。
例如,要将自动装配候选状态限制为名称以Repository结尾的任何bean,
可以提供一个值* Repository。
要提供多个模式,请在逗号分隔的列表中定义它们。
bean definition的autowire-candidate属性的显式值true或false优先级更高。
对于这样的bean,模式匹配规则不适用。

These techniques are useful for beans that you never want to be injected into other beans by autowiring. It does not mean that an excluded bean cannot itself be configured by using autowiring. Rather, the bean itself is not a candidate for autowiring other beans.

这些技术对于您绝不希望通过自动装配将其注入到其他bean中的bean非常有用。
这并不意味着被排除的bean本身不能使用自动装配进行配置。
相反,该bean本身不是自动连接其他bean的候选对象。

1.4.6. Method Injection
方法注入

In most application scenarios, most beans in the container are singletons. When a singleton bean needs to collaborate with another singleton bean or a non-singleton bean needs to collaborate with another non-singleton bean, you typically handle the dependency by defining one bean as a property of the other. A problem arises when the bean lifecycles are different. Suppose singleton bean A needs to use non-singleton (prototype) bean B, perhaps on each method invocation on A. The container creates the singleton bean A only once, and thus only gets one opportunity to set the properties. The container cannot provide bean A with a new instance of bean B every time one is needed.

在大多数应用程序场景中,容器中的大多数bean都是singleton类型。
当一个 singleton类型的bean需要与另一个singleton类型的bean协作时,
或者一个非singleton类型的bean需要与另一个非singleton类型的bean协作时,
通常通过将一个bean定义为另一个bean的属性来处理依赖关系。
当bean的生命周期不同时,问题就出现了。
假设 singleton类型的bean A需要使用非singleton类型的(prototype类型)bean B,
可能在A的每个方法调用上。
容器只创建singleton类型的bean一次,因此只有一次机会设置属性。
容器不能在每次需要bean B的时候都向bean A提供一个新的实例。

A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean(“B”) call to the container ask for (a typically new) bean B instance every time bean A needs it. The following example shows this approach:

一个解决办法是放弃一些控制反转。
您可以通过实现applicationcontextAware接口,以及在每次bean A需要bean B实例时,
通过对容器进行getBean(“B”)调用来让bean A知道容器。
下面的例子展示了这种方法:

forego  
 英  [fɔːˈɡəʊ]   美  [fɔːrˈɡoʊ]
vt. 放弃;居先;在……之前


// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;

// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class CommandManager implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public Object process(Map commandState) {
        // grab a new instance of the appropriate Command
        Command command = createCommand();
        // set the state on the (hopefully brand new) Command instance
        command.setState(commandState);
        return command.execute();
    }

    protected Command createCommand() {
        // notice the Spring API dependency!
        return this.applicationContext.getBean("command", Command.class);
    }

    public void setApplicationContext(
            ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

The preceding is not desirable, because the business code is aware of and coupled to the Spring Framework. Method Injection, a somewhat advanced feature of the Spring IoC container, lets you handle this use case cleanly.

前面的方法并不可取,因为业务代码知道Spring框架并与之耦合。
方法注入是Spring IoC容器的一种高级特性,它允许您干净地处理这个用例。

You can read more about the motivation for Method Injection in this blog entry(https://spring.io/blog/2004/08/06/method-injection/).

您可以在这篇博客文章中阅读更多关于方法注入动机的内容。

Lookup Method Injection
查找方法注入

Lookup method injection is the ability of the container to override methods on container-managed beans and return the lookup result for another named bean in the container. The lookup typically involves a prototype bean, as in the scenario described in the preceding section. The Spring Framework implements this method injection by using bytecode generation from the CGLIB library to dynamically generate a subclass that overrides the method.

查找方法注入是容器重载容器管理bean上的方法并返回容器中另一个已命名bean的
查找结果的能力。
查找通常涉及prototype类型的bean,如上一节所描述的场景。
Spring框架通过使用来自CGLIB库的字节码生成动态生成重载该方法的子类来实现
这种方法注入。

  • For this dynamic subclassing to work, the class that the Spring bean container subclasses cannot be final, and the method to be overridden cannot be final, either.
  • Unit-testing a class that has an abstract method requires you to subclass the class yourself and to supply a stub implementation of the abstract method.
  • Concrete methods are also necessary for component scanning, which requires concrete classes to pick up.
  • A further key limitation is that lookup methods do not work with factory methods and in particular not with @Bean methods in configuration classes, since, in that case, the container is not in charge of creating the instance and therefore cannot create a runtime-generated subclass on the fly.
* 要使这个动态子类工作,Spring bean容器子类的类不能是final,
  被覆盖的方法也不能是final。
* 单元测试一个有抽象方法的类需要你创建这个类的子类并提供抽象方法的stub实现。
* 组件扫描也需要具体方法,需要具体类拾取。
* 进一步关键的限制是查找方法不使用工厂方法,特别是在方法配置类的@Bean方法,
因为,在这种情况下,容器是不负责创建实例,因此不能创建一个运行时生成的子类。

In the case of the CommandManager class in the previous code snippet, the Spring container dynamically overrides the implementation of the createCommand() method. The CommandManager class does not have any Spring dependencies, as the reworked example shows:

对于前面代码片段中的CommandManager类,Spring容器动态重载
createCommand()方法的实现。
CommandManager类没有任何Spring依赖项,正如修改后的示例所示:

package fiona.apple;

// no more Spring imports!

public abstract class CommandManager {

    public Object process(Object commandState) {
        // grab a new instance of the appropriate Command interface
        Command command = createCommand();
        // set the state on the (hopefully brand new) Command instance
        command.setState(commandState);
        return command.execute();
    }

    // okay... but where is the implementation of this method?
    protected abstract Command createCommand();
}

In the client class that contains the method to be injected (the CommandManager in this case), the method to be injected requires a signature of the following form:

在包含要注入的方法的客户端类中(本例为CommandManager),
要注入的方法需要以下形式的签名:

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

If the method is abstract, the dynamically-generated subclass implements the method. Otherwise, the dynamically-generated subclass overrides the concrete method defined in the original class. Consider the following example:

如果方法是抽象的,则动态生成的子类实现该方法。
否则,动态生成的子类将重载在原始类中定义的具体方法。考虑下面的例子:

<!-- a stateful bean deployed as a prototype (non-singleton) -->
<bean id="myCommand" class="fiona.apple.AsyncCommand" scope="prototype">
    <!-- inject dependencies here as required -->
</bean>

<!-- commandProcessor uses statefulCommandHelper -->
<bean id="commandManager" class="fiona.apple.CommandManager">
    <lookup-method name="createCommand" bean="myCommand"/>
</bean>

The bean identified as commandManager calls its own createCommand() method whenever it needs a new instance of the myCommand bean. You must be careful to deploy the myCommand bean as a prototype if that is actually what is needed. If it is a singleton, the same instance of the myCommand bean is returned each time.

标识为commandManager的bean在需要myCommand bean的新实例时
调用自己的createCommand()方法。
如果真的需要将myCommand bean部署为prototype类型,则必须小心。
如果是singleton类型,则每次返回myCommand bean的相同实例。

Alternatively, within the annotation-based component model, you can declare a lookup method through the @Lookup annotation, as the following example shows:

或者,在基于注释的组件模型中,您可以通过@Lookup注释声明一个查找方法,
如下面的示例所示:

public abstract class CommandManager {

    public Object process(Object commandState) {
        Command command = createCommand();
        command.setState(commandState);
        return command.execute();
    }

    @Lookup("myCommand")
    protected abstract Command createCommand();
}

Or, more idiomatically, you can rely on the target bean getting resolved against the declared return type of the lookup method:

或者,更习惯的做法是,您可以依赖于根据查找方法声明的返回类型解析目标bean:

public abstract class CommandManager {

    public Object process(Object commandState) {
        MyCommand command = createCommand();
        command.setState(commandState);
        return command.execute();
    }

    @Lookup
    protected abstract MyCommand createCommand();
}

Note that you should typically declare such annotated lookup methods with a concrete stub implementation, in order for them to be compatible with Spring’s component scanning rules where abstract classes get ignored by default. This limitation does not apply to explicitly registered or explicitly imported bean classes.

请注意,您通常应该使用具体的stub实现来声明这种带注释的查找方法,
以便它们与Spring的组件扫描规则兼容,其中抽象类在默认情况下会被忽略。
此限制不适用于显式注册或显式导入的bean类。


Another way of accessing differently scoped target beans is an ObjectFactory/ Provider injection point. See Scoped Beans as Dependencies.

访问不同作用域的目标bean的另一种方法是ObjectFactory/ Provider注入点。
参阅Scoped Beans as Dependencies 章节。

You may also find the ServiceLocatorFactoryBean (in the org.springframework.beans.factory.config package) to be useful.

您还可以发现ServiceLocatorFactoryBean非常有用(org.springframework.beans.factory.config包中)。

Arbitrary Method Replacement

A less useful form of method injection than lookup method injection is the ability to replace arbitrary methods in a managed bean with another method implementation. You can safely skip the rest of this section until you actually need this functionality.

任意的方法替换
方法注入不如查找方法注入有用的形式是用另一个方法实现替换托管bean中的
任意方法的能力。
您可以安全地跳过本节的其余部分,直到您真正需要此功能。

With XML-based configuration metadata, you can use the replaced-method element to replace an existing method implementation with another, for a deployed bean. Consider the following class, which has a method called computeValue that we want to override:

对于基于xml的配置元数据,可以使用replaced-method元素将已部署bean的
现有方法实现替换为另一个方法实现。
考虑下面的类,它有一个名为computeValue的方法,我们希望重载它:

public class MyValueCalculator {

    public String computeValue(String input) {
        // some real code...
    }

    // some other methods...
}

A class that implements the org.springframework.beans.factory.support.MethodReplacer interface provides the new method definition, as the following example shows:

实现org.springframework.bean.factory.support.MethodReplacer接口的类
提供了新的方法定义,如下面的示例所示:

/**
 * meant to be used to override the existing computeValue(String)
 * implementation in MyValueCalculator
 */
public class ReplacementComputeValue implements MethodReplacer {

    public Object reimplement(Object o, Method m, Object[] args) throws Throwable {
        // get the input value, work with it, and return a computed result
        String input = (String) args[0];
        ...
        return ...;
    }
}

The bean definition to deploy the original class and specify the method override would resemble the following example:

部署原始类并指定方法覆盖的bean definition类似于下面的示例:

<bean id="myValueCalculator" class="x.y.z.MyValueCalculator">
    <!-- arbitrary method replacement -->
    <replaced-method name="computeValue" replacer="replacementComputeValue">
        <arg-type>String</arg-type>
    </replaced-method>
</bean>

<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>

You can use one or more elements within the element to indicate the method signature of the method being overridden. The signature for the arguments is necessary only if the method is overloaded and multiple variants exist within the class. For convenience, the type string for an argument may be a substring of the fully qualified type name. For example, the following all match java.lang.String:

可以使用<replacement-method/>元素中的一个或多个<argtype/>元素来指示
被覆盖方法的方法签名。
只有当方法被重载并且类中存在多个变体时,参数的签名才有必要。
为了方便,参数的类型字符串可以是完全限定类型名的子字符串。
例如,以下所有匹配java.lang.String:

java.lang.String
String
Str

Because the number of arguments is often enough to distinguish between each possible choice, this shortcut can save a lot of typing, by letting you type only the shortest string that matches an argument type.

由于参数的数量通常足以区分每种可能的选择,因此通过只输入与参数类型匹配的最短字符串,
此快捷方式可以节省大量输入。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值