1.3.2. Instantiating beans
1.3.2. 实例化beans
A bean definition is essentially a recipe for creating one or more objects. The container looks at the recipe for a named bean when asked and uses the configuration metadata encapsulated by that bean definition to create (or acquire) an actual object.
Bean定义本质上是创建一个或多个对象的方法。容器在被询问时会查看命名bean的配方,并使用该bean定义封装的配置元数据来创建(或获取)实际对象。
If you use XML-based configuration metadata, you specify the type (or class) of object that is to be instantiated in the class attribute of the element. This class attribute (which, internally, is a Class property on a BeanDefinition instance) is usually mandatory. (For exceptions, see Instantiation by Using an Instance Factory Method and Bean Definition Inheritance.) You can use the Class property in one of two ways:
如果使用基于XML的配置元数据,则在元素的class属性中指定要实例化的对象的类型(或类)。这个class属性(在内部是BeanDefinition实例的Class属性)通常是必需的。 (有关异常,请参见使用实例工厂方法实例化和Bean定义继承。)可以通过以下两种方式之一使用Class属性:
- Typically, to specify the bean class to be constructed in the case where the container itself directly creates the bean by calling its constructor reflectively, somewhat equivalent to Java code with the new operator.
- 通常,在容器本身通过反射性地调用其构造函数直接创建Bean的情况下,指定要构造的Bean类,这在某种程度上等同于使用new运算符的Java代码。
- To specify the actual class containing the static factory method that will be invoked to create the object, in the less common case where the container invokes a static factory method on a class to create the bean. The object type returned from the invocation of the static factory method may be the same class or another class entirely.
- 要指定包含要创建对象的静态工厂方法的实际类,在不太常见的情况下,容器将在类上调用静态工厂方法以创建Bean。从静态工厂方法的调用返回的对象类型可以是同一类,也可以是完全不同的另一类。
Nested class names
嵌套类名
If you want to configure a bean definition for a static nested class, you have to use the binary name of the nested class.
如果要为静态嵌套类配置一个bean定义,则必须使用嵌套类的二进制名称。
For example, if you have a class called SomeThing in the com.example package, and this SomeThing class has a static nested class called OtherThing, they can be separated by a dollar sign ($) or a dot (.). So the value of the class attribute in a bean definition would be com.example.SomeThing $ OtherThing or com.example.SomeThing.OtherThing.
例如,如果您在 com.example 包中有一个名为 SomeThing 的类,并且此 SomeThing 类有一个名为 OtherThing 的静态嵌套类,则它们可以用美元符号 ($) 或点 (.) 分隔。 所以 bean 定义中类属性的值是 com.example.SomeThing $OtherThing 或 com.example.SomeThing.OtherThing。
Instantiation with a constructor
用构造函数实例化
When you create a bean by the constructor approach, all normal classes are usable by and compatible with Spring. That is, the class being developed does not need to implement any specific interfaces or to be coded in a specific fashion. Simply specifying the bean class should suffice. However, depending on what type of IoC you use for that specific bean, you may need a default (empty) constructor.
当您通过构造函数方法创建一个bean时,所有普通类都可以被Spring使用并兼容。也就是说,正在开发的类不需要实现任何特定的接口或以特定的方式编码。只需指定bean类就足够了。但是,根据您用于特定bean的IoC类型,您可能需要一个默认(空)构造函数。
The Spring IoC container can manage virtually any class you want it to manage; it is not limited to managing true JavaBeans. Most Spring users prefer actual JavaBeans with only a default (no-argument) constructor and appropriate setters and getters modeled after the properties in the container. You can also have more exotic non-bean-style classes in your container. If, for example, you need to use a legacy connection pool that absolutely does not adhere to the JavaBean specification, Spring can manage it as well.
Spring IoC容器几乎可以管理任何您想要管理的类;它不限于管理真正的JavaBeans。大多数Spring用户更喜欢实际的JavaBeans,它只有一个默认的(无参数)构造函数,以及在容器中的属性之后建模的合适的setter和getter。您的容器中还可以有更多具有异国情调的非Bean风格的类。例如,如果您需要使用绝对不符合JavaBean规范的传统连接池,Spring也可以管理它。
With XML-based configuration metadata you can specify your bean class as follows:
使用基于XML的配置元数据,您可以按如下方式指定您的bean类:
<bean id="exampleBean" class="examples.ExampleBean"/>
<bean name="anotherExample" class="examples.ExampleBeanTwo"/>
For details about the mechanism for supplying arguments to the constructor (if required) and setting object instance properties after the object is constructed, see Injecting Dependencies.
有关在构造对象后为参数提供参数(如果需要)和设置对象实例属性的机制的详细信息,请参阅注入依赖项。
Instantiation with a static factory method
使用静态工厂方法实例化
When defining a bean that you create with a static factory method, you use the class attribute to specify the class containing the static factory method and an attribute named factory-method to specify the name of the factory method itself. You should be able to call this method (with optional arguments as described later) and return a live object, which subsequently is treated as if it had been created through a constructor. One use for such a bean definition is to call static factories in legacy code.
在定义一个使用静态工厂方法创建的bean时,可以使用class属性来指定包含静态工厂方法的类和名为factory-method的属性,以指定工厂方法本身的名称。您应该能够调用此方法(使用后面介绍的可选参数)并返回一个活动对象,随后将其视为通过构造函数创建的对象。这种bean定义的一个用途是在传统代码中调用静态工厂。
The following bean definition specifies that the bean will be created by calling a factory-method. The definition does not specify the type (class) of the returned object, only the class containing the factory method. In this example, the createInstance() method must be a static method.
以下bean定义指定将通过调用工厂方法来创建该bean。该定义没有指定返回对象的类型(类),而只指定了包含工厂方法的类。在这个例子中,createInstance()方法必须是一个静态方法。
<bean id="clientService"
class="examples.ClientService"
factory-method="createInstance"/>
The following example shows a class that would work with the preceding bean definition:
以下示例显示了可与前面的bean定义一起使用的类:
public class ClientService {
private static ClientService clientService = new ClientService();
private ClientService() {}
public static ClientService createInstance() {
return clientService;
}
}
For details about the mechanism for supplying (optional) arguments to the factory method and setting object instance properties after the object is returned from the factory, see Dependencies and configuration in detail.
有关在从工厂返回对象之后向工厂方法提供参数(可选)并设置对象实例属性的机制的详细信息,请参阅依赖关系和详细配置。
Instantiation using an instance factory method
使用实例工厂方法实例化
Similar to instantiation through a static factory method, instantiation with an instance factory method invokes a non-static method of an existing bean from the container to create a new bean. To use this mechanism, leave the class attribute empty, and in the factory-bean attribute, specify the name of a bean in the current (or parent/ancestor) container that contains the instance method that is to be invoked to create the object. Set the name of the factory method itself with the factory-methodattribute.
与通过静态工厂方法实例化类似,使用实例工厂方法的实例化从容器调用现有bean的非静态方法来创建新的bean。 要使用此机制,请将类属性保留为空,并在factory-bean属性中指定当前(或父/祖代)容器中包含要调用以创建对象的实例方法的bean的名称。 使用factory-method属性设置工厂方法本身的名称。
<!-- the factory bean, which contains a method called createInstance() -->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
<!-- inject any dependencies required by this locator bean -->
</bean>
<!-- the bean to be created via the factory bean -->
<bean id="clientService" factory-bean="serviceLocator"
factory-method="createClientServiceInstance"/>
The following example shows the corresponding class:
以下示例显示了相应的类:
public class DefaultServiceLocator {
private static ClientService clientService = new ClientServiceImpl();
public ClientService createClientServiceInstance() {
return clientService;
}
}
One factory class can also hold more than one factory method as shown here:
一个工厂类也可以拥有多个工厂方法,如下所示:
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
<!-- inject any dependencies required by this locator bean -->
</bean>
<bean id="clientService"
factory-bean="serviceLocator"
factory-method="createClientServiceInstance"/>
<bean id="accountService"
factory-bean="serviceLocator"
factory-method="createAccountServiceInstance"/>
The following example shows the corresponding class:
以下示例显示了相应的类:
public class DefaultServiceLocator {
private static ClientService clientService = new ClientServiceImpl();
private static AccountService accountService = new AccountServiceImpl();
public ClientService createClientServiceInstance() {
return clientService;
}
public AccountService createAccountServiceInstance() {
return accountService;
}
}
This approach shows that the factory bean itself can be managed and configured through dependency injection (DI). See Dependencies and configuration in detail.
这种方法表明,工厂bean本身可以通过依赖注入(DI)进行管理和配置。 详细信息请参阅依赖关系和配置。
In Spring documentation, factory bean refers to a bean that is configured in the Spring container that will create objects through an instance or static factory method. By contrast, FactoryBean (notice the capitalization) refers to a Spring-specific FactoryBean.
在Spring文档中,工厂bean指的是在Spring容器中配置的bean,它将通过实例或静态工厂方法创建对象。 相反,FactoryBean(注意大写字母)是指特定于Spring的FactoryBean。
Determining a Bean’s Runtime Type
确定 Bean 的运行时类型
The runtime type of a specific bean is non-trivial to determine. A specified class in the bean metadata definition is just an initial class reference, potentially combined with a declared factory
method or being a FactoryBean class which may lead to a different runtime type of the bean, or not
being set at all in case of an instance-level factory method (which is resolved via the specified
factory-bean name instead). Additionally, AOP proxying may wrap a bean instance with an
interface-based proxy with limited exposure of the target bean’s actual type (just its implemented
interfaces).
确定特定 bean 的运行时类型并非易事。 bean 元数据定义中的指定类只是一个初始类引用,可能与声明的工厂方法组合或作为 FactoryBean 类,这可能导致 bean 的不同运行时类型,或者在实例的情况下根本没有设置 级工厂方法(而是通过指定的工厂 bean 名称解析)。 此外,AOP 代理可以用基于接口的代理包装一个 bean 实例,并限制目标 bean 的实际类型(仅其实现的接口)的暴露。
The recommended way to find out about the actual runtime type of a particular bean is a
BeanFactory.getType call for the specified bean name. This takes all of the above cases into account
and returns the type of object that a BeanFactory.getBean call is going to return for the same bean
name.
查找特定 bean 的实际运行时类型的推荐方法是对指定 bean 名称的 BeanFactory.getType 调用。 这将所有上述情况都考虑在内,并返回 BeanFactory.getBean 调用将为相同的 bean 名称返回的对象类型。