Spring参考文档翻译06--IOC容器04

1.4. Dependencies

依赖项

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 定义到完全实现的应用程序,其中对象协作以实现目标。

1.4.1. Dependency Injection

依赖注入

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) 是一个过程,对象仅通过构造函数参数、工厂方法的参数或对象实例在构造或从工厂方法返回。然后容器在创建 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.

使用 DI 原则,代码更干净,当对象具有依赖关系时,解耦更有效。对象不查找其依赖项,也不知道依赖项的位置或类别。结果,您的类变得更容易测试,特别是当依赖关系在接口或抽象基类上时,它们允许在单元测试中使用存根或模拟实现。

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

DI 存在两个主要变体:基于构造函数的依赖注入基于 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:

基于构造函数的 DI 是通过容器调用具有多个参数的构造函数来完成的,每个参数代表一个依赖项。调用static带有特定参数的工厂方法来构造 bean 几乎是等价的,本次讨论将类似地对待构造函数和static工厂方法的参数。以下示例显示了一个只能通过构造函数注入进行依赖注入的类:

public class SimpleMovieLister {
    // the SimpleMovieLister has a dependency on a MovieFinder
    private final 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 定义的构造函数参数中不存在潜在的歧义,则在 bean 定义中定义构造函数参数的顺序是在实例化 bean 时将这些参数提供给适当构造函数的顺序。考虑以下类:

package x.y;
​
public class ThingOne {
​
    public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {
        // ...
    }
}

Assuming that the 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 <constructor-arg/> element.

假设ThingTwoThingThree类不通过继承相关,则不存在潜在的歧义。因此,以下配置工作正常,您无需在 <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 <value>true</value>, 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 无法确定值的类型,因此无法在没有帮助的情况下按类型匹配。考虑以下类:

package examples;
​
public class ExampleBean {
​
    // Number of years to calculate the Ultimate Answer
    private final int years;
​
    // The Answer to Life, the Universe, and Everything
    private final 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.
索引从 0 开始

Constructor argument name

构造函数参数名称

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

您还可以使用构造函数参数名称来消除值歧义,如下例所示:

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

记住,为了让这个在容器外工作,你的代码必须能够通过debug标识来编译,以至于Spring可以从构造器中寻找参数名称。如果你不能或不想通过debug标识来编译你的代码,你可以使用@ConstructorProperties JDK注解来显式地命名你的构造器参数。接下来可以看到案例类:

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的依赖注入

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 的 DI 是通过容器在调用无参数构造函数或无参数static工厂方法来实例化 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,不依赖于容器特定的接口、基类或注释。

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.

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

Constructor-based or setter-based DI?

基于构造器依赖注入或基于setter依赖注入

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 的 DI,因此将构造函数用于强制依赖项并将 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 团队通常提倡构造函数注入,因为它允许您将应用程序组件实现为不可变对象,并确保所需的依赖项不是null. 此外,构造函数注入的组件总是以完全初始化的状态返回给客户端(调用)代码。附带说明一下,大量的构造函数参数是一种不好的代码气味,这意味着该类可能有太多的职责,应该重构以更好地解决适当的关注点分离问题。

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 MBean进行管理是 setter 注入的一个引人注目的用例。

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.

使用对特定类最有意义的 DI 样式。有时,在处理您没有源代码的第三方类时,会为您做出选择。例如,如果第三方类没有公开任何 setter 方法,那么构造函数注入可能是 DI 的唯一可用形式。

Dependency Resolution Process

依赖解决过程

The container performs bean dependency resolution as follows:

容器执行 bean 依赖解析如下:

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

    使用ApplicationContext描述所有 bean 的配置元数据创建和初始化。配置元数据可以由 XML、Java 代码或注释指定。

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

    对于每个 bean,它的依赖关系以属性、构造函数参数或静态工厂方法的参数的形式表示(如果您使用它而不是普通的构造函数)。这些依赖项在实际创建 bean 时提供给 bean。

  • Each property or constructor argument is an actual definition of the value to set, or a reference to another bean in the container.

    每一个属性或构造器参数都是一个实际定义,他的值被容器中的其他bean设置或引用。

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

    作为值的每个属性或构造函数参数都从其指定格式转换为该属性或构造函数参数的实际类型。默认情况下,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 属性本身。在创建容器时会创建单例范围并设置为预实例化(默认)的 Bean。范围在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.

如果您主要使用构造函数注入,则可能会创建无法解决的循环依赖场景。

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.

例如:A类通过构造函数注入需要B类的实例,B类通过构造函数注入需要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注入来配置循环依赖。

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 eagerly pre-instantiated.

您通常可以相信 Spring 会做正确的事情。它在容器加载时检测配置问题,例如对不存在的 bean 和循环依赖项的引用。在实际创建 bean 时,Spring 会尽可能晚地设置属性并解析依赖关系。这意味着,如果在创建该对象或其依赖项之一时出现问题,则正确加载的 Spring 容器稍后可以在您请求对象时生成异常——例如,bean 由于丢失或无效而引发异常财产。某些配置问题的这种潜在延迟可见性就是为什么ApplicationContext默认情况下,实现预实例化单例 bean。以在实际需要之前创建这些 bean 的一些前期时间和内存为代价,您会在创建这些 bean 时发现配置问题ApplicationContext,而不是稍后。您仍然可以覆盖此默认行为,以便单例 bean 延迟初始化,而不是急切地预先实例化。

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 被实例化(如果它不是预先实例化的单例) ),设置其依赖关系,并调用相关的生命周期方法(例如配置的 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 的 DI。Spring XML 配置文件的一小部分指定了一些 bean 定义,如下所示:

<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 文件中指定的属性相匹配。以下示例使用基于构造函数的 DI:

<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 定义中指定的构造函数参数用作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 被告知调用static工厂方法来返回对象的实例,而不是使用构造函数:

<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 <constructor-arg/> 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.

工厂方法的参数static<constructor-arg/>元素提供,就像实际使用了构造函数一样。工厂方法返回的类的类型不必与包含static工厂方法的类的类型相同(尽管在本例中是这样)。实例(非静态)工厂方法可以以基本相同的方式使用(除了使用factory-bean属性而不是class属性),因此我们不在这里讨论这些细节。

1.4.2. Dependencies and Configuration in Detail

详细的依赖关系和配置

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

如上一节所述,您可以将 bean 属性和构造函数参数定义为对其他托管 bean(协作者)的引用或内联定义的值。为此, Spring 的基于 XML 的配置元数据支持其<property/>和元素中的子元素类型。<constructor-arg/>

Straight Values (Primitives, Strings, and so on)

直值(基元、字符串等)

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

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

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

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="misterkaoli"/>
​
</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 IDEASpring Tools for Eclipse )。强烈推荐这种 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 <value/> element into a java.util.Properties instance by using the JavaBeans PropertyEditor mechanism. This is a nice shortcut, and is one of a few places where the Spring team do favor the use of the nested <value/> element over the value attribute style.

Spring容器将<value/>元素中的文本转换为 java.util.Properties实例,使用JavaBeans PropertyEditor机制。这是一个很好的快捷方式,也是Spring团队喜欢使用嵌套的<value/>元素而不是值属性样式的几个地方之一。

The idref element

idref标签

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

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 确实存在。在第二个变体中,不对传递给beantargetName属性的值执行验证。只有在实际实例化 beanclient时才会发现拼写错误(很可能是致命的结果) 。client如果client bean 是一个原型bean,那么这个拼写错误和产生的异常可能只有在容器部署很久之后才会被发现。

The local attribute on the idref element is no longer supported in the 4.0 beans XSD, since it does not provide value over a regular bean reference any more. Change your existing idref local references to idref bean when upgrading to the 4.0 schema.
4.0 bean XSD 不再支持元素上的local属性idref,因为它不再提供常规bean引用的值。在升级到 4.0 架构时 更改现有idref local引用。idref bean

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

<idref/>元素带来价值的常见地方(至少在 Spring 2.0 之前的版本中)是在 bean 定义中的AOP 拦截器配置中。ProxyFactoryBean在指定拦截器名称时使用<idref/>元素可以防止您拼错拦截器 ID。

References to Other Beans (Collaborators)

对其他 Bean 的引用(合作者)

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

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

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

bean通过标签的属性指定目标bean<ref/>是最通用的形式,它允许创建对同一容器或父容器中的任何bean的引用,而不管它是否在同一个XML文件中。属性的值 bean可以与目标bean 的属性相同,id或者与目标bean 的属性中的值之一相同name。以下示例显示了如何使用ref元素:

<ref bean="someBean"/>

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

通过属性指定目标 beanparent会创建对当前容器的父容器中的 bean 的引用。属性的值parent 可以与目标 bean 的id属性或目标 bean 的属性中的值之一相同name。目标 bean 必须在当前 bean 的父容器中。您应该使用此 bean 引用变体,主要是当您具有容器层次结构并且希望使用与父 bean 同名的代理将现有 bean 包装在父容器中时。以下一对清单显示了如何使用该parent属性:

<!-- in the parent context -->
<bean id="accountService" class="com.something.SimpleAccountService">
    <!-- insert dependencies as required 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 beans XSD不再支持“ref”元素的“local”属性,因为它不再提供常规“bean”引用的值。升级到4.0模式时,将现有的“ref local”引用更改为“ref bean”。

Inner Beans

内部Beans

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

“<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 定义不需要定义的 ID 或名称。如果指定,容器不会使用这样的值作为标识符。容器在创建时也会忽略该scope标志,因为内部 bean 始终是匿名的,并且始终使用外部 bean 创建。不可能独立访问内部 bean 或将它们注入到协作 bean 中,而不是注入封闭 bean。

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

作为一个极端情况,可以从自定义范围接收销毁回调 - 例如,对于包含在单例 bean 中的请求范围内的内部 bean。内部 bean 实例的创建与其包含的 bean 相关联,但销毁回调让它参与请求范围的生命周期。这不是常见的情况。内部 bean 通常只是共享其包含 bean 的范围。

Collections

集合

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

“<list/>”、“set/>”、“map/>”和“<props/>”元素分别设置Java集合类型“list”、“set”、“map”和“properties”的属性和参数。以下示例显示了如何使用它们:

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

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

映射键或值或设置值的值也可以是以下任何元素:

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

Collection Merging

集合合并

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

Spring容器还支持合并集合。应用程序开发人员可以定义父<list/>、<map/>、<set/>或<props/>元素,并使子<list/>、<map/>、<set/>或<props/>元素继承并重写父集合中的值。也就是说,子集合的值是父集合和子集合的元素合并的结果,子集合元素覆盖父集合中指定的值。

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

本节关于合并讨论了父子 bean 机制。不熟悉 parent 和 child bean 定义的读者可能希望在继续之前阅读 相关部分

The following example demonstrates collection merging:

以下示例演示了集合合并:

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

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

注意,在“child”bean定义的“adminEmails”属性的“<props/>”元素上使用了“merge=true”属性。当容器解析并实例化“child”bean时,生成的实例有一个“adminEmails”属性集合,其中包含将子的“adminEmails”集合与父的“adminEmails”集合合并的结果。以下列表显示了结果:

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

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

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

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

这种合并行为同样适用于<list/><map/><set/> 集合类型。在<list/>元素的特定情况下,与List集合类型相关联的语义(即ordered 值集合的概念)得到维护。父级的值在所有子级列表的值之前。对于MapSetProperties集合类型,不存在排序。Map因此,对于容器内部使用的关联、SetProperties实现类型下的集合类型,没有任何排序语义有效。

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.

您不能合并不同的集合类型(例如 aMap和 a List)。如果您确实尝试这样做,Exception则会抛出适当的。该merge属性必须在较低的继承的子定义中指定。在父集合定义上指定merge属性是多余的,不会导致所需的合并。

Strongly-typed collection

强类型集合

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

由于 Java 对泛型类型的支持,您可以使用强类型集合。也就是说,可以声明一个Collection类型,使其只能包含(例如)String元素。如果使用 Spring 将强类型依赖注入Collection到 bean 中,则可以利用 Spring 的类型转换支持,以便强类型Collection 实例的元素在添加到Collection. 以下 Java 类和 bean 定义显示了如何执行此操作:

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属性something准备好注入时,强类型的元素类型的泛型信息Map<String, Float>可以通过反射获得。因此,Spring 的类型转换基础结构将各种 value 元素识别为 type Float,并将字符串值(9.992.753.99)转换为实际Float类型。

Null and Empty String Values

Null和Empty字符串值

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 将属性等的空参数视为空参数Strings。以下基于 XML 的配置元数据片段将该email属性设置为空 String值 ("")。

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

The preceding example is equivalent to the following Java code:

前面的示例等效于以下 Java 代码:

exampleBean.setEmail("");

The <null/> 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

带有 p 命名空间的 XML 快捷方式

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

p-namespace 允许您使用bean元素的属性(而不是嵌套 <property/>元素)来描述协作 bean 或两者的属性值。

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 模式定义。本章讨论的beans配置格式在 XML Schema 文档中定义。但是,p-namespace 没有在 XSD 文件中定义,仅存在于 Spring 的核心中。

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-namespace):

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

该示例显示了email在 bean 定义中调用的 p-namespace 中的一个属性。这告诉 Spring 包含一个属性声明。如前所述,p-namespace 没有架构定义,因此您可以将属性的名称设置为属性名称。

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

下一个示例包括另外两个 bean 定义,它们都引用了另一个 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 <property name="spouse" ref="jane"/> to create a reference from bean john to bean jane, the second bean definition uses p:spouse-ref="jane" as an attribute to do the exact same thing. In this case, spouse is the property name, whereas the -ref part indicates that this is not a straight value but rather a reference to another bean.

此示例不仅包括使用 p 命名空间的属性值,而且还使用特殊格式来声明属性引用。第一个 bean 定义用于<property name="spouse" ref="jane"/>创建从 bean john到 bean的引用jane,而第二个 bean 定义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

带有 c 命名空间的 XML 快捷方式

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.

类似于[p命名空间的XML快捷方式](Core Technologies),Spring 3.1中引入的c-namespace,允许内联属性来配置构造函数参数,而不是嵌套的“constructor 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)。同样,它需要在 XML 文件中声明,即使它没有在 XSD 模式中定义(它存在于 Spring 核心中)。

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 <constructor-arg> 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 throughout 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 定义:

<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属性,它有一个sammy属性,最后的sammy属性被设置为123。为了使其工作,在构造bean后,某物的fred属性和fred的bob属性不能为null。否则,将抛出NullPointerException。

1.4.3. Using depends-on

使用 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-depen”属性可以显式地强制在初始化使用该元素的bean之前初始化一个或多个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 的依赖,请提供 bean 名称列表作为depends-on属性值(逗号、空格和分号是有效的分隔符):

<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属性既可以指定初始化时间依赖项,也可以指定对应的销毁时间依赖项(仅在单例bean 的情况下)。定义与给定 bean 的关系的从属 beandepends-on首先被销毁,然后给定 bean 本身被销毁。这样,depends-on也可以控制关机顺序。

1.4.4. Lazy-initialized Beans

延迟初始化的 Bean

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.

默认情况下,作为初始化过程的一部分,ApplicationContext实现会急切地创建和配置所有 单例bean。通常,这种预实例化是可取的,因为配置或周围环境中的错误会立即发现,而不是几小时甚至几天之后。当这种行为不可取时,您可以通过将 bean 定义标记为延迟初始化来防止单例 bean 的预实例化。延迟初始化的 bean 告诉 IoC 容器在第一次被请求时创建一个 bean 实例,而不是在启动时。

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

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

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

当前面的配置被 an 使用ApplicationContext时,lazybean 不会在ApplicationContext启动时急切地预实例化,而not.lazybean 是急切地预实例化的。

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 是未延迟初始化的单例 bean 的依赖项时,将ApplicationContext在启动时创建延迟初始化的 bean,因为它必须满足单例的依赖项。延迟初始化的 bean 被注入到没有延迟初始化的其他地方的单例 bean 中。

You can also control lazy-initialization at the container level by using the default-lazy-init attribute on the <beans/> element, as the following example shows:

您还可以通过使用元素上的 default-lazy-init属性在容器级别控制延迟初始化<beans/>,如以下示例所示:

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

Spring 容器可以自动装配协作 bean 之间的关系。您可以通过检查ApplicationContext. 自动装配具有以下优点:

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

    自动装配可以显着减少指定属性或构造函数参数的需要。(本章其他地方讨论的 bean 模板等其他机制 在这方面也很有价值。)

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

    随着对象的发展,自动装配可以更新配置。例如,如果您需要向类添加依赖项,则可以自动满足该依赖项,而无需修改配置。因此,自动装配在开发过程中特别有用,而不会在代码库变得更稳定时否定切换到显式装配的选项。

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 <bean/> 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 的配置元数据时(请参阅依赖注入),您可以使用元素的autowire属性为 bean 定义指定自动装配模式。<bean/>自动装配功能有四种模式。您指定每个 bean 的自动装配,因此可以选择要自动装配的那些。下表描述了四种自动装配模式:

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.
(默认)不自动装配。Bean 引用必须由ref元素定义。对于较大的部署,不建议更改默认设置,因为明确指定协作者可以提供更大的控制力和清晰度。在某种程度上,它记录了系统的结构。
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.
按属性名称自动装配。Spring 寻找与需要自动装配的属性同名的 bean。例如,如果一个 bean 定义被设置为按名称自动装配并且它包含一个master属性(即它有一个 setMaster(..)方法),那么 Spring 会查找一个命名的 bean 定义master并使用它来设置该属性。
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).
如果容器中恰好存在一个属性类型的 bean,则让属性自动装配。如果存在多个,则会抛出一个致命异常,这表明您可能不会byType对该 bean 使用自动装配。如果没有匹配的 bean,则不会发生任何事情(未设置属性)。
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.
类似于byType但适用于构造函数参数。如果容器中没有一个构造函数参数类型的 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.

使用byTypeconstructor自动装配模式,您可以连线数组和类型化集合。在这种情况下,将提供容器中与预期类型匹配的所有自动装配候选者来满足依赖关系。Map如果预期的键类型是 ,您可以自动装配强类型实例String。自动装配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.

    “property”和“constructor-arg”设置中的显式依赖项始终覆盖自动连接。您不能自动连接简单属性,例如基元、“字符串”和“类”(以及此类简单属性的数组)。这种限制是出于设计。

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

    自动装配不如显式装配精确。尽管如前表中所述,Spring 会小心避免猜测可能会产生意想不到的结果的歧义。Spring 管理的对象之间的关系不再明确记录。

  • Wiring information may not be available to tools that may generate documentation from a Spring container.

    从 Spring 容器生成文档的工具可能无法使用接线信息。

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

    容器内的多个 bean 定义可能与要自动装配的 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.

    autowire-candidate通过将其属性设置为 来避免对 bean 定义进行自动装配false,如下一节所述

  • Designate a single bean definition as the primary candidate by setting the primary attribute of its <bean/> element to true.

    通过将其<bean/>元素的主要属性设置为true,将单个bean定义指定为主要候选。

  • Implement the more fine-grained control available with annotation-based configuration, as described in Annotation-based Container Configuration.

    使用基于注释的配置实现更细粒度的控制,如基于注释的容器配置中所述。

Excluding a Bean from Autowiring

从自动装配中排除一个bean

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

在每个bean的基础上,可以将bean从自动连接中排除。在Spring的XML格式中,将元素的autowire候选属性设置为false。该容器使特定的bean定义对自动连接基础结构(包括注释样式配置,例如@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 <beans/> 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名称的模式匹配来限制autowire候选。顶级“<beans/>”元素在其“default autowire候选者”属性中接受一个或多个模式。例如,要将autowire候选状态限制为名称以“Repository”结尾的任何bean,请提供值“*Repository”。要提供多个模式,请在逗号分隔的列表中定义它们。bean定义的“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是单例。当一个单例bean需要与另一个单例bean协作,或者一个非单例bean需要与另一个非单例bean协作时,通常通过将一个bean定义为另一个bean的属性来处理依赖关系。当bean生命周期不同时,就会出现问题。假设单例bean A需要使用非单例(原型)bean B,可能是在A上的每个方法调用上。容器只创建单例bean A一次,因此只有一次机会设置属性。容器不能在每次需要时为bean A提供bean B的新实例。

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接口,并在每次BeanA需要时对容器进行getBean(“B”)调用来请求(通常是新的)BeanB实例,从而使BeanA了解容器。以下示例显示了这种方法:

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

您可以在此博客条目中阅读有关方法注入动机的更多信息 。

Lookup Method Injection

Lookup方法注入

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的查找结果的能力。查找通常涉及一个原型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是 。 对具有abstract方法的类进行单元测试需要您自己子类化该类并提供该abstract方法的存根实现。 组件扫描也需要具体的方法,这需要具体的类来拾取。 另一个关键限制是查找方法不适用于工厂方法,特别是不适@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:

如果方法是abstract,则动态生成的子类实现该方法。否则,动态生成的子类将覆盖原始类中定义的具体方法。考虑以下示例:

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

当需要“myCommand”bean的新实例时,标识为“commandManager”的bean调用自己的“createCommand()”方法。如果需要的话,您必须小心地将“myCommand”bean部署为原型。如果它是一个单例,每次都返回相同的“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) {
        Command command = createCommand();
        command.setState(commandState);
        return command.execute();
    }
​
    @Lookup
    protected abstract Command 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.

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

Another way of accessing differently scoped target beans is an ObjectFactory/ Provider injection point. See Scoped Beans as Dependencies.You may also find the ServiceLocatorFactoryBean (in the org.springframework.beans.factory.config package) to be useful.
访问不同范围的目标 bean 的另一种方法是ObjectFactory/ Provider注入点。请参阅Scoped Beans as Dependencies。您可能还会发现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.beans.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 定义类似于以下示例:

<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 <arg-type/> elements within the <replaced-method/> 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:

您可以在<replaced-method/>元素中使用一个或多个<arg-type/>元素来指示被重写方法的方法签名。只有当方法重载并且类中存在多个变体时,才需要参数的签名。为方便起见,参数的类型字符串可以是完全限定类型名的子字符串。例如,以下所有匹配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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值