1.3.2. Instantiating Beans 实例化bean
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 <bean/>
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的配置元数据,则指定要在<bean/>
元素的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 is invoked to create the object, in the less common case where the container invokes astatic
factory method on a class to create the bean. The object type returned from the invocation of thestatic
factory method may be the same class or another class entirely.指定包含静态工厂方法的实际类,该方法被调用来创建对象,在不太常见的情况下,容器调用类上的静态工厂方法来创建bean。从调用静态工厂方法返回的对象类型可以是同一个类,也可以完全是另一个类。
Inner 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
, the value of the class
attribute on a bean definition would be com.example.SomeThing$OtherThing
.
例如,如果在com.example
这个SomeThing
类有一个名为OtherThing
的静态嵌套类,bean定义上的class
属性的值为com.example.someThing$OtherThing
。
Notice the use of the $
character in the name to separate the nested class name from the outer class name.
请注意在名称中使用$字符将嵌套类名与外部类名分开。
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.
springioc容器实际上可以管理任何你想要它管理的类。它不仅限于管理真正的javabean。大多数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, use the class
attribute to specify the class that contains 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 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. The following example shows how to specify a factory 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 by 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 or 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-method
attribute. The following example shows how to configure such a bean:
与通过静态工厂方法实例化类似,使用实例工厂方法的实例化从容器调用现有bean的非静态方法来创建新的bean。要使用此机制,请将class属性留空,并在factory bean属性中指定当前(或父级或祖先)容器中的bean的名称,该容器包含要调用以创建对象的实例方法。使用factory method属性设置工厂方法本身的名称。下面的示例演示如何配置此类bean:
<!-- 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 the following example shows:
一个工厂类也可以包含多个工厂方法,如下例所示:
<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本身可以通过依赖注入(dependency injection,DI)进行管理和配置。请详细查看依赖项和配置。
In Spring documentation, “factory bean” refers to a bean that is configured in the Spring container and that creates objects through an instance or static factory method. By contrast, FactoryBean (notice the capitalization) refers to a Spring-specific FactoryBean implementation class. |
|
---|---|
在Spring文档中,“factory bean”是指在Spring容器中配置的、通过实例或静态工厂方法创建对象的bean。比照FactoryBean(注意)实现了特定的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的不同运行时类型,或者在实例级工厂方法(通过指定的 factory-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的实际运行时类型的推荐方法是BeanFactory.getType
调用指定的bean名称。这将考虑上述所有情况并返回BeanFactory.getBean
调用将返回相同的bean名称。