一. 填充Bean属性
<bean id="zoo" class="Zoo">
<property name="zooName" value="zooName" />
<property name="cat" ref="cat" />
</bean>
<bean id="cat" class="Cat"></bean>
在已获取到对象实例的基础上,这个阶段的任务就是为Bean的属性赋值,比如上图的定义,需要为zoo对象的两个属性“zooName”和“cat”赋值。具体的步骤如下,
1). 首先通过RootBeanDefinition对象的MutablePropertyValues getPropertyValues()方法,获取待赋值给bean属性的属性值集合对象。
2). 然后给予实例化敏感bean后处理器(InstantiationAwareBeanPostProcessor)有机会修改bean实例,调用boolean postProcessAfterInstantiation(Object bean, String beanName)方法对bean实例执行后处理。PS:在Spring启动阶段已经完成了对所有bean后处理的创建和注册,这块内容后续博客会分析。
3). 处理自动装配,前提是用户配置了自动装配策略(BY Name or By Type),默认是禁止自动装配的,并且自动装配也不支持基本类型(诸如Integer、String等)。所谓自动装配就是不需要显式为属性指定值,Spring自动根据属性名称或属性类型,找寻恰当的bean对象为其赋值。经过这个步骤,待赋值给bean属性的属性值变多了。4). 再次调用实例化敏感bean后处理器,使其有机会在把属性值赋值给bean属性之前,再次执行后处理。这次调用的是后处理器的
PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
方法,从第一个方法参数可以看出,本次后处理主要是针对待赋值给bean属性的属性值的。
5). 对属性值执行解析, 可以参考上篇博客的这段论述。
6). 把属性值赋值给bean对象。
通过Bean包装器实现该能功能,在Spring内部对bean属性的存取都是通过BeanWrapper实现的,具体可以参看这篇博客。 《Spring3.1.0实现原理分析(四).属性访问器(PropertyAccessor)》
BeanWrapper.setPropertyValues(MutablePropertyValues);
二. 初始化Bean
1). 判断bean对象是否实现了Aware相关接口。
a. 如果bean对象实现了BeanNameAware接口,则调用bean对象的setBeanName(String)方法,意味这bean对象可以获取自身的Id。
b. 如果bean对象实现了BeanClassLoaderAware接口,则调用其setBeanClassLoader方法,bean对象可以获取bean工厂的类加载器。
c. 如果bean对象实现了BeanFactoryAware接口,则调用其setBeanFactory(bf)方法,bean对象可以获取bean工厂。
2). 调用所有bean后处理器的如下方法,在初始化之前对bean执行后处理。
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
3). 初始化bean
如果bean实现了InitializingBean接口,则先调用该接口的void afterPropertiesSet() 方法。其次,如果用户配置bean时指定了init-method="..."属性值,则调用该方法对bean执行初始化操作。
4). 再次调用所有bean后处理器的如下方法,在初始化之后对bean执行后处理。
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;三. 登记善后处理 (仅适用于单例bean)
登记善后处理需要同时满足两个条件,分别是:
- bean的生命周期是单例。
- bean实现了可销毁接口(DisposableBean) 或者 配置了销毁方法(destroy-method="...") 或者 容器中存在销毁敏感bean后处理器(DestructionAwareBeanPostProcessor)。
- bean对象是否实现了可销毁接口(DisposableBean) 。
- 如果bean配置了销毁方法(destroy-method="..."),则获取销毁方法名称及方法对象。
- 从当前容器的bean后处理器集合中,过滤出所有销毁敏感bean后处理器(DestructionAwareBeanPostProcessor),作为列表赋值给成员变量。
被创建的DisposableBeanAdapter对象,会被存储到DefaultSingletonBeanRegistry类的成员变量Map<String, Object> disposableBeans中,其中key是bean's Id。当Spring容器被关闭时(即ConfigurableApplicationContext#close()方法被调用),会调用存储在disposableBeans中的所有DisposableBeanAdapter对象的destroy()方法,执行善后处理,具体执行顺序如下,
- 调用销毁敏感bean后处理器的void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;方法。
- 调用DisposableBean接口的destroy()方法。
- 调用用户配置的销毁方法。
补充:对于web应用ConfigurableApplicationContext#close()方法是在ContextLoaderListener监听器中被自动触发的,但是对于桌面应用,如果希望“善后处理”得到执行需要手动调用ConfigurableApplicationContext#registerShutdownHook()方法,当java虚拟机被关闭时,会回调注册的方法。
四. 注册单例Bean(仅适用于单例bean)
- 单例bean对象置入DefaultSingletonBeanRegistry类的成员变量singletonObjects 。
- 把单例bean对象的Id置入DefaultSingletonBeanRegistry类的成员变量registeredSingletons。
/**
* 单例对象缓存(key:bean名称;value:单例bean对象)
*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();
/**
* 已注册的单例bean名称集合
*/
private final Set<String> registeredSingletons = new LinkedHashSet<String>(16);