Spring Bean 生命周期
BeanFactory和ApplicationContext是Spring两种很重要的容器,前者提供了最基本的依赖注入的支持,而后者在继承前者的基础进行了功能的拓展,例如增加了事件传播,资源访问和国际化的消息访问等功能。
概括来说主要有四个阶段:实例化,初始化,使用,销毁。
Bean 作用范围
常用的Bean作用范围:singleton和prototype
singleton
在默认情况下,Spring的ApplicationContext容器在启动时,自动实例化所有singleton的Bean并缓存于容器中.虽然启动时会花费一些时间,但带来两个好处:首先对Bean提前的实例化操作会及早发现一些潜在的配置问题.其次Bean以缓存的方式保存,当运行时使用到该Bean时就无须再实例化了,加快了运行效率.如果用户不希望在容器启动时提前实例化singleton的Bean,可以通过lazy-init属性进行控制.
prototype
在默认情况下,Spring容器在启动时不实例化prototype的Bean.此外,Spring容器将prototype的Bean交给调用者后,就不再管理它的生命周期.
ApplicationContext Bean生命周期:
Spring Bean的完整生命周期从创建Spring容器开始,直到最终Spring容器销毁Bean,这其中包含了一系列关键点。
流程图

若容器注册了以上各种接口,程序那么将会按照以上的流程进行。下面将仔细讲解各接口作用。
各种接口方法分类
Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:
1、Bean自身的方法:这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法
2、Bean级生命周期接口方法:这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法
3、容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor和 BeanPostProcessor这两个接口实现,一般称它们的实现类为“后处理器”。容器中每个bean初始化都要经过这一步。
4、工厂后处理器接口BeanFactoryPostProcessor方法:这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的,在应用上下文装配配置文件之后立即调用。
流程说明
- 首先容器启动后,会对
scope为singleton且非懒加载(lazy-init=false)的bean进行实例化, - 按照
Bean定义信息配置信息,注入所有的属性 - 如果
Bean实现了BeanNameAware接口,会回调该接口的setBeanName()方法,传入该Bean的id,此时该Bean就获得了自己在配置文件中的id - 如果
Bean实现了BeanFactoryAware接口,会回调该接口的setBeanFactory()方法,传入该Bean的BeanFactory,这样该Bean就获得了自己所在的BeanFactory - 如果
Bean实现了ApplicationContextAware接口,会回调该接口的setApplicationContext()方法,传入该Bean的ApplicationContext,这样该Bean就获得了自己所在的ApplicationContext - 如果有
Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessBeforeInitialzation()方法 - 如果
Bean实现了InitializingBean接口,则会回调该接口的afterPropertiesSet()方法 - 如果
Bean配置了init-method方法,则会执行init-method配置的方法 - 如果有
Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessAfterInitialization()方法 - 经过流程9之后,就可以正式使用该
Bean了,对于scope为singleton的Bean,Spring的ioc容器中会缓存一份该bean的实例,而对于scope为prototype的Bean,每次被调用都会new一个新的对象,生命周期就交给调用方管理了,不再是Spring容器进行管理了 - 容器关闭后,如果
Bean实现了DisposableBean接口,则会回调该接口的destroy()方法 - 如果
Bean配置了destroy-method方法,则会执行destroy-method配置的方法,至此,整个Bean的生命周期结束
BeanFactory Bean生命周期
BeanFactoty容器中, Bean的生命周期如下图所示,与ApplicationContext相比,有如下几点不同:
1.BeanFactory容器中,不会调用ApplicationContextAware接口的setApplicationContext()方法
2.BeanPostProcessor接口的postProcessBeforeInitialzation()方法和postProcessAfterInitialization()方法不会自动调用,必须自己通过代码手动注册
3.BeanFactory容器启动的时候,不会去实例化所有Bean,包括所有scope为singleton且非懒加载的Bean也是一样,而是在调用的时候去实例化。
流程图

流程说明
- 当调用者通过
getBean(name)向 容器寻找Bean时,如果容器注册了org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,在实例bean之前,将调用该接口的postProcessBeforeInstantiation()方法 - 容器寻找
Bean的定义信息,并将其实例化 - 使用依赖注入,
Spring按照Bean定义信息配置Bean的所有属性 - 如果
Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的id - 如果实现了
BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身 - 如果
BeanPostProcessor和Bean关联,那么它们的postProcessBeforeInitialization()方法将被调用(需要手动进行注册!) - 如果
Bean实现了InitializingBean接口,则会回调该接口的afterPropertiesSet()方法 - 如果
Bean指定了init-method方法,就会调用init-method方法 - 如果
BeanPostProcessor和Bean关联,那么它的postProcessAfterInitialization()方法将被调用(需要手动注册!) - 现在
Bean已经可以使用了scope为singleton的Bean缓存在Spring IOC容器中scope为prototype的Bean生命周期交给客户端
- 销毁
- 如果
Bean实现了DisposableBean接口,destory()方法将会被调用 - 如果配置了
destory-method方法,就调用这个方法
- 如果
演示
用一个简单的Spring Bean来演示一下Spring Bean的生命周期。
1、首先是一个简单的Spring Bean,调用Bean自身的方法和Bean级生命周期接口方法,为了方便演示,它实现了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这4个接口,同时有2个方法,对应配置文件中<bean>的init-method和destroy-method。如下:
|
|
2、接下来是演示BeanPostProcessor接口的方法,如下:
|
|
如上,BeanPostProcessor接口包括2个方法postProcessAfterInitialization和postProcessBeforeInitialization,这两个方法的第一个参数都是要处理的Bean对象,第二个参数都是Bean的name。返回值也都是要处理的Bean对象。
3、InstantiationAwareBeanPostProcessor 接口本质是BeanPostProcessor的子接口,一般我们继承Spring为其提供的适配器类InstantiationAwareBeanPostProcessorAdapter来使用它,如下:
|
|
这个有3个方法,其中第二个方法postProcessAfterInitialization就是重写了BeanPostProcessor的方法。第三个方法postProcessPropertyValues用来操作属性,返回值也应该是PropertyValues对象。
4、工厂后处理器接口方法,如下:
|
|
BeanFactoryPostProcessor 可以修改 bean 的配置信息而 BeanPostProcessor 不能
|
|
5、配置文件如下beans.xml,使用ApplicationContext,处理器不用手动注册:
|
|
6、测试一下:
|
|
关闭容器使用的是实际是AbstractApplicationContext的钩子方法。
7、结果:
|
|
总结
Bean的完整生命周期从 spring 容器开始实例化 bean 开始,到销毁。可以从三点来理解
1、bean自身的方法:包括构造方法、 set 方法、 init-method 指定的方法、 destroy-method 指定的方法
2、bean级生命周期接口方法:如BeanNameAware 、 BeanFactoryAware 等这些接口方法由 bean类实现
3、容器级生命周期接口方法:有InstantiationAwareBeanPostProcessor 、 BeanPostProcessor等。一般称为后处理器。他们一般不由bean 本身实现,独立存在,注册到 spring 容器中。 Spring 通过接口反射预先知道,当 spring 容器创建任何 bean 时,这些后处理器都会发生作用。所以他们是全局的,用户可以通过编码对只感兴趣的 bean 进行处理