如前所述,bean是使用配置诠释中的bean定义创建的,在container内部这些bean的定义用一个BeanDefinition对象来表示,具有一下诠释:
bean定义中的配置信息会被转换成BeanDefenition的属性,如下:
property |
---|
Class |
Name |
Scope |
Constructor arguments |
Properties |
Autowiring mode |
Lazy initialization mode |
Initialization method |
Destruction method |
除了允许配置诠释中的定义外,ApplicationContext还允许Container外部对象的注册。通过调用ApplicationContext的getBeanFactory方法得到一个BeanFactory实例,这个实例是其中BeanFactory的其中一个实现DefaultListableBeanFactory,再使用这个实例的registerSingleton或者registerBeanDefinition方法即可完成。
注意:Container外的单例对象应该尽早的注册,以免在Autowiring或其他的Spring内部进行的步骤中发生错误。由于一定程度上,Container允许一定程度上的诠释的覆盖(override),新注册的bean不会得到正式的支持,从而引发并发上的访问问题,在Container中状态不一致等问题。
每一个Beans拥有一个或多个标识符,这些标识符在主持它的容器中必须是唯一的。一个bean可以拥有一个id标识符和多个name标识符。如果不显示地给一个bean提供标识符,Container会生成一个,但这样就没法在其他地方引用这个bean。不提供标识符通常与inner beans或使用autowiring collaborators有关。
Container生成标识符的规则与一般的命名方式相同,在不适用的时候保留类名。
通常在配置诠释中配置一个bean的name,但是也允许在bean的定义配置诠释外配置一个bean的别名,这通常用在一个每个子系统都有各自配置的大系统中。在xml中从外部配置一个bean的别名:
<alias name="fromName" alias="toName"/>
使用java配置时,从@Bean的属性中配置别名。
如上所述,一个BeanDefinition是一个创建Bean的配置单,Container通过访问BeanDefinition中封装的信息来创建一个实际的bean对象。
BeanDefinition的Class属性,或者说配置诠释中的Class属性,有以下两种应用方式:
这种方式下所有常规类都是可用的,并且与Spring兼容,这表示这个被开发的类不需要实现任何接口或者以一种特定的方式coded。仅仅提供类型即可。不过,也许你需要给这个类写一个默认的无参构造方法。
大多数人喜欢写无参构造方法以及getter和setter方法以便Container使用。Container中也可以管理一些不那么符合上面这种方式写出的类,例如一些遗留下来的,完全没有依附于Spring的类。
如上所述,BeanDefinition的Class属性可以指定一个拥有静态工厂方法的类。这种方式的一个用处是调用遗留代码中的静态工厂方法。
这样的bean的配置诠释的一个例子:
<bean id="clientService"
class="examples.ClientService"
factory-method="createInstance"/>
注意,使用哪一个工厂方法是需要指定明确的。
与调用静态工厂方法实例化一个类的方式类似,不过不要指定需要实例化的bean的类型,通过factory-bean指定容器中的另一个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"/>
这里需要指出的是,Container中的bean是可以作为一个工厂对象去实例化另外的bean的。
有个易混淆的东西:在Spring中factory-bean指生成bean的工厂对象,而FactoryBean是指一个FactoryBean的特定实现。
一个bean的配置诠释中的类只是一个最初的参考,这个类与一个工厂方法组合在一起,或者是一个FactoryBean类,这两种情况可能导致bean的不同运行时类型,或者在一个使用实例的工厂方法实例化的情况下完全没有指定。其他的,AOP代理可能在接口基础上包装一个bean实例以免暴露这个bean的真正运行时类型。
要找出一个bean的运行时类型,建议对这个bean(通过bean的标识符)使用BeanFactory.getType,这个方式将上面所有的情况纳入了考虑,并且返回的类型和对特定表示符使用BeanFactory.getBean(这个方法需要两个参数name和type)同样的类型。
原文:https://www.cnblogs.com/kicey/p/14865315.html