IOC容器和Bean的生命周期
一、IOC容器的初始化过程
IOC容器是一个Map(可以通过 getBean()
获取到对应key的value,value存放的是对象)
先放一张整体的流程图
关于上图的说明:
-
BeanDefinition
<!--假设有如下的bean信息--> <context:property-placeholder location="dbconfig.properties"/> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="driverClassName" value="${jdbc.driverclass}"/> <property name="url" value="${jdbc.url}"/> </bean>
BeanDefinition的bean信息中属性的值是占位符形式(
${xxx}
),并没有赋予真正的值 -
两种后置处理器
-
BeanFactoryPostProcessor
- 扩展增强的是
BeanFactory
BeanFactoryPostProcessor
还完成了@Bean、@Component
等注解的解析 - 扩展增强的是
-
BeanPostProcessor
- 扩展增强的是
bean
对象
- 扩展增强的是
-
-
BeanFactory
是IOC容器的入口
-
IOC容器的初始化过程
- bean的定义信息 →
BeanDefinitionReader
读取bean信息 →BeanDefinition
→BeanFactoryPostProcessor
→BeanFactory
- bean的定义信息 →
二、Bean的生命周期
BeanFactory中调用反射代码实例化bean,在堆中开辟一块空间,此时属性都是默认值,接下来开始初始化。
Bean生命周期图及文字描述:
-
Spring启动,查找并加载需要被Spring管理的Bean,进行Bean的实例化(如果有多个bean,则需要循环遍历进行初始化)
-
Bean实例化后调用set()方法对Bean的属性进行赋值
-
如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法
- 当需要在普通对象中获取容器相关的内部对象时,就需要实现
*Aware
接口
- 当需要在普通对象中获取容器相关的内部对象时,就需要实现
-
如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
-
如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用的上下文引用传入进来
-
与上述类似,如果实现了其余Aware接口,就要调用对应的方法,具体顺序如下图所示:
-
如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法
-
如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法
-
如果Bean在配置文件中定义了
init-method
属性,执行指定的方法 -
如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法
-
此时,Bean已经准备就绪,可以被应用程序使用了,他们将一直驻留在应用上下文中,直到应用上下文被销毁
-
销毁过程:如果Bean实现了DisposableBean接口,Spring将调用它的destory()接口方法
-
如果Bean在配置文件中定义了
destory-method
属性,执行指定的方法
注意:
在实例化操作之前,会进行准备BeanPostProcessor、监听器、广播器等工作(监听器、广播器利用了观察者模式,可以在Bean生命周期的不同阶段处理不同的工作,比如可以在实例化、填充属性等操作完成之后自动打印一句话)