本篇文章记录一下Spring中,BeanFactory 与 ApplicationContext 中 bean 的生命周期过程,参考网上资料,总结如下
BeanFactory
当调用者调用
getBean()
想容器请求一个bean时,如果容器注册了 InstantiationAwareBeanPostProcessor(实现了BeanPostProcessor)接口,
则实例化bean之前,调用该接口的postProcessBeforeInstantiation()
根据配置调用bean的构造器/工厂方法 实例化bean
如果容器注册了 InstantiationAwareBeanPostProcessor(实现了BeanPostProcessor)接口, 则实例化bean之后,调用该接口的
postProcessAfterInstantiation()
如果bean配置了 属性信息, 则 这一步将属性设置到bean对应的属性中, 在设置每一个属性值之前, 调用 InstantiationAwareBeanPostProcessor 的 postProcessPropertyValues()
设置属性值
如果bean 实现了 BeanNameAware 接口,则 执行 setBeanName(),将xml文件里的 beanid 设置到 bean中
如果bean 实现了 BeanFactoryAware 接口,则 执行 setBeanFactory(),将BeanFactory 容器实例 设置到 bean中
如果 beanFactory 装配了 BeanPostProcessor 接口,则 调用 BeanPostProcessor.postProcessBeforeInitialization(Object bean, String beanName)对bean进行加工
bean: 当前增在处理的 bean beanName: 当前bean的配置名 返回值为 加工处理后的bean
要使用BeanPostProcessor回调,就必须先在容器中注册实现该接口的类,那么如何注册呢?
BeanFactory和ApplicationContext容器的注册方式不大一样:若使用BeanFactory,则必须要显示的调用其addBeanPostProcessor()方法进行注册,
参数为BeanPostProcessor实现类的实例;如果是使用ApplicationContext,那么容器会在配置文件在中自动寻找实现了BeanPostProcessor接口的Bean,然后自动注册,
我们要做的只是配置一个BeanPostProcessor实现类的Bean就可以了。
如果bean实现了 InitializingBean 接口 ,则调用 InitializingBean#afterProperiesSet
如果在bean中通过init-method属性定义了初始化方法,则将执行这个方法。
BeanPostProcessor 后处理利器定义了两个方法, postProcessBeforeInitialization(8 中调用) postProcessAfterInitialization(Object bean, String beanName)
此方法调用时 spring 再次获得 对bean进行加工处理的机会如果
中定义 bean 的作用范围是 scope=’prototype’, 则将bean返回给调用者,由调用者负责bean后续生命周期管理,spring不在管理这个bean的生命周期
如果中定义 bean 的作用范围是 scope=’singleton’,当将bean 放入SpringIOC容器的缓存池中, 并将 bean 引用返回给调用者,spring继续对 bean 进行后续的生命周期管理 如果当前的bean的作用范围是singleton,且bean实现了DisposableBean接口,在容器关闭的时候,则将调用接口的destory方法。
对于singleton的bean,如果bean通过destory-method属性指定了bean的销毁方法,那么在spring容器关闭的时候,就会执行该方法。
这些方法大致可以归为四类:
- Bean自身的方法:自身的方法也就是在bean中通过init-method和destory-method指定的方法。
- Bean级生命周期接口方法:如BeanNameAware,BeanFactoryAware,InitializingBean和DisposableBean,这些接口方法由Bean类直接实现。
- 容器级生命周期接口方法:InstantiationAwareBeanPostProcessor和BeanPostProcessor接口实现,一般称它们的实现类为“后处理器”。
- 后处理器接口一般不由bean实现, 他们独立于bean, 一般以容器附加的形式注册到 spring容器中,并通过接口反射为spring容器扫描识别,
- 当容器创建任何bean的时候后处理器都会发生作用。所以这些后处理器的影响是全局性的
- 当然用户可以合理的编写后处理器,使其只对感兴趣的bean进行处理
- 工厂处理器接口方法:包括AspectJWeavingEnabler,CustomAutowireConfigurer,ConfigurationClassPostProcessor等方法。工厂后处理器也是容器级的,在应用上下文装配文件后立即调用。
ApplicationContext
使用ApplicationContext & bean(scope=singleton) ,name容器加载时这些bean 就会被实例化。好处是可以预先加载,缺点是耗内存
如果使用的是 BeanFactory, 当实例化bean时不会直接实例化,而是等到使用(调动 getBean(String beanName))时才会实例化. BeanFactory会延迟初始化所投的的Bean. 好处是节约内存, 缺点是速度慢
一般没有特殊要求,使用ApplicationContext. ApplicationContext 实现了 ListableBeanFactory & HierarchicalBeanFactory,具有BeanFactory的所有功能, 并且还额外提供了 许多高级功能
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
}
- 提供文本解析工具,包括对国际化的支持
- 提供载入资源文件的通用方法,图片
- 可以向注册为监听器的Bean 发送事件
ApplicationContext 经常见到的三种实现
ClassPathXmlApplicationContext
从类路径中加载。
FileSystemXmlApplicationContext
从文件系统加载。
XmlWebApplicationContext
从Web系统中加载。
ApplicationContext中 bean生命周期 与 BeanFactory中 Bean生命周期类似
不同得是 如果bean实现了 ApplicationContextAware 接口, 将调用 setApplicationContext()
此外如果配置文件中配置了工厂后处理器接口,BeanFactoryPostProcessor
的实现类,则应用上下文装配完配置文件之后,初始化bean之前,会调用这些BeanFactoryPostProcessor对配置信息进行加工处理,如CustomerEditorConfigure
, PropertyPlaceHolderConfigure
. 如果配置了多个最好实现 Order 接口,spring可以按顺序执行他们。这些实现的作用是什么呢?
工厂后处理器是容器级别的,仅在应用上下文初始化时调用一次,其目的是完成一些配置文件的加工处理工作。
ApplicationContext在启动时,将首先为配置文件中的每个bean生成BeanDefination对象,BeanDefination
bean的生命周期不但和其实现的接口有关,还和它的作用范围相关。