3 如何实例化 bean?
BeanDefinition可看做是创建对象的配方。容器在被询问时,会查看被命名过的bean的BeanDefinition,并使用该BeanDefinition中的配置元数据创建(或直接从缓存池获取)对应的对象实例。
比如在XML方式下,在<bean/>标签的class属性指定要实例化的对象的类型。这个class属性,其实就是BeanDefinition实例的Class属性,因此该属性一般强制必须指定。
可通过如下方式使用Class属性来实例化 bean:
3.1 构造器
在容器自身通过反射调用其构造器直接创建bean时,指定要构造的bean类,类似new运算符。该方式下,类基本上都能被Spring兼容。即bean类无需实现任何特定接口或以特定方式编码。指定bean类即可。注意,根据所用的IoC类型,有时需要一个默认的无参构造器。
3.2 静态工厂方法
指定包含将要创建对象的静态工厂方法的实际类,容器将在类上调用静态工厂方法以创建bean。
定义使用静态工厂方法创建的bean时,可使用class属性来指定包含静态工厂方法的类,并使用factory-method属性指定工厂方法本身的名称。开发者应该能够调用此方法并返回一个存活对象,该对象随后将被视为通过构造器创建的。
这种BeanDefinition的一种用法是在老代码中调用static工厂。
看个例子,如下BeanDefinition指定将通过调用工厂方法来创建bean。该定义不指定返回对象的类型,而仅指定包含工厂方法的类。该示例中的initInstance()方法须是静态方法。
<bean id="serverService" class="examples.ServerService" factory-method="initInstance"/>
可与上面的BeanDefinition协同的类:
public class ServerService { private static ServerService serverService = new ServerService(); private ServerService() {} public static ServerService createInstance() { return serverService; } }
3.3 实例工厂方法
使用该方式实例化会从容器中调用现有bean的非静态方法来创建新bean。要使用此机制,需将class属性置空,并在factory-bean属性中,在当前(或父/祖先)容器中指定包含要创建该对象的实例方法的bean的名称。factory-method设置工厂方法本身的名称。
示例如下,来看看如何配置这样的bean:
相应的类:
一个工厂类也可以容纳一个以上的工厂方法,如下:
这种方式还表明,即使是工厂bean也可以通过依赖注入进行管理和配置。
“factory bean”是指在Spring容器中配置并通过实例或静态工厂方法创建对象的bean。相比之下,FactoryBean是指特定于Spring的FactoryBean实现类。
4 如何确定Bean的运行时类型?
bean元数据定义中的指定类只是初始类引用,可能结合使用的如下方式之一:
声明的工厂方法
FactoryBean类,该情况可能导致bean的运行时类型不同
实例级工厂方法(通过指定的factory-bean名称解析),该情况下直接就不设置了
因此,看起来确定bean运行时类型绝非易事,该如何准确获取呢?
BeanFactory.getType
推荐调用 BeanFactory.getType确定bean的运行时类型。
该方法可确定给定名称bean的类型。更确切地,返回针对相同bean名称的BeanFactory.getBean调用将返回的对象的类型。
且该方法的实现考虑了前面穷举的所有情况,并针对于FactoryBean ,返回FactoryBean所创建的对象类型,和FactoryBean.getObjectType()返回一致。
参考