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 进行处理