7.3.2 bean的实例化
7.3.2 bean的实例化
bean的定义本质上是创建一个或多个对象的配方。当被请求时,容器在配方中查找指定名称的bean,使用bean定义中封装的配置元数据来创建(或得到)一个实际的对象。
如果使用基于XML的配置元数据,在<bean/>
元素的class
属性中指定被实例化对象的类型(或类)。class
属性通常是强制性的,它在内部实质是BeanDefinition
实例的Class
属性。(例外情况,请见使用实例工厂方法实例化一节和7.7 bean定义的继承。)
您可以以两种方式使用Class
属性:
- 通常,在容器本身通过反射调用类的构造方法直接创建bean的情况下,需要指定bean的要被构建的类,一定程度上相当于Java代码中使用new操作符。
- 在容器调用一个类的
静态
工厂方法创建bean这种不太常见的情况下,需要指定含有静态
工厂方法的实际类。调用静态
工厂方法返回的对象类型可能是同一个类,也可能是另一个类。
内部类的名称
如果要为一个
静态
嵌套类配置bean定义,必须使用嵌套类的二进制名称。例如,如果在com.example
包中有一个叫Foo
的类,同时这个类中有一个叫Bar
的静态
嵌套类,那么bean定义中'class'
属性的值将是:
com.example.Foo$Bar
请注意,在名称中使用
$
字符将嵌套类的名和外部类的名分开。
使用构造方法实例化
当以构造方法的方式创建bean,所有普通的类对Spring而言都是可用且兼容的。也就是说,正在开发的类不需要实现任何特定的接口或以特定的方式进行编码。仅指定bean的类应该就足够了。不过,取决于为具体的bean使用什么类型的IoC,可能需要一个默认(空)的构造方法。
实际上,Spring的IoC容器能管理您想让它管理的任何类,不限于管理JavaBean。大多数Spring的用户更喜欢容器中实际的JavaBean,只有一个默认(无参)构造方法和在属性之后模式化的setter和getter方法。容器中也可以有更奇特的非bean样式的类。例如,如果您需要使用一个绝对不符合JavaBean规范的遗留的连接池,Spring同样可以管理它。
使用基于XML的配置元数据,可以如下指定bean的类:
<bean class="examples.ExampleBean"/>
<bean name="anotherExample" class="examples.ExampleBeanTwo"/>
关于向构造方法提供参数(如果需要)的机制以及在对象创建后设置对象实例属性的细节,请参阅依赖注入。
使用静态工厂方法实例化
当定义一个通过静态工厂方法创建的bean时,使用class
属性来指定拥有该静态工厂方法的类,同时使用名为factory-method
的属性指定该工厂方法的名字。要确保可以调用这个方法(可以带有可选的参数,这一点稍后再介绍),并返回一个像是通过构造方法创建的对象。这样的bean定义的一个用法是在遗留代码中调用静态
工厂。
下面的bean定义指定了bean将通过调用一个工厂方法来创建。定义并不指定返回对象的类型(类),仅指定拥有工厂方法的类。在这个例子中,createInstance()
方法必须是一个静态
方法。
bean
class="examples.ClientService"
factory-method="createInstance"/>
public class ClientService {
private static ClientService clientService = new ClientService();
private ClientService() {}
public static ClientService createInstance() {
return clientService;
}
}
有关向工厂方法提供(可选)参数以及在对象从工厂返回后设置对象实例属性的细节,请参阅依赖和配置的细节
使用实例工厂方法实例化
与通过静态工厂方法进行实例化类似,通过一个实例工厂方法进行实例化会调用容器中一个现有bean的非静态的方法来创建一个新的bean。要使用这个机制,置class
属性为空,而在factory-bean
属性中指定当前(或父/祖先)容器中拥有被调用用来创建对象的实例方法的bean的名字,设置factory-method
属性为该工厂方法的名字。
<!-- the factory bean, which contains a method called createInstance() -->
<bean class="examples.DefaultServiceLocator">
<!-- inject any dependencies required by this locator bean -->
</bean>
<!-- the bean to be created via the factory bean -->
<bean
factory-bean="serviceLocator"
factory-method="createClientServiceInstance"/>
public class DefaultServiceLocator {
private static ClientService clientService = new ClientServiceImpl();
private DefaultServiceLocator() {}
public ClientService createClientServiceInstance() {
return clientService;
}
}
一个工厂类可以持有多于一个的工厂方法,如下所示:
<bean class="examples.DefaultServiceLocator">
<!-- inject any dependencies required by this locator bean -->
</bean>
<bean
factory-bean="serviceLocator"
factory-method="createClientServiceInstance"/>
<bean
factory-bean="serviceLocator"
factory-method="createAccountServiceInstance"/>
public class DefaultServiceLocator {
private static ClientService clientService = new ClientServiceImpl();
private static AccountService accountService = new AccountServiceImpl();
private DefaultServiceLocator() {}
public ClientService createClientServiceInstance() {
return clientService;
}
public AccountService createAccountServiceInstance() {
return accountService;
}
}
这种做法表明,工厂bean本身也可以通过依赖注入(DI)来配置和管理。参阅依赖和配置的细节