概述:Spring框架核心模块中的IOC容器为我们提供了创建Bean和管理Bean以及管理Bean的生命周期的功能,IOC思想的引入后,不在通过new手动创建对象,这一切都交给了Spring框架完成,掌握Spring中Bean的生命周期有助于我们对IOC思想的理解,下面详细描述Bean的声明周期。
Bean的生命周期:实例化——>初始化——>操作使用——>销毁
一、实例化:
- 加载xml配置文件,解析获取配置中的每个的信息,封装成一个个的BeanDefinition对象;
- 将BeanDefinition存储在一个名为beanDefinitionMap的Map中;
- ApplicationContext底层遍历beanDefinitionMap,创建Bean实例对象;
Spring的2种后处理器:
1、BeanFactoryPostProcessor:Bean工厂后处理器,在BeanDefinitionMap填充完毕,Bean实例 化之前执行;
2、BeanPostProcessor:Bean后处理器,一般在Bean实例化之后,填充到单例池singletonObjects 之前执行。
二、初始化:
Bean创建之后还仅仅是个"半成品",还需要对Bean实例的属性进行填充、执 行一些Aware 接口方法、执行BeanPostProcessor方法、执行InitializingBean接口的初始化方 法、执行自定义初始化init方法等。
初始化操作需要:创建好的Bean实例对象,被存储到一个名为singletonObjects的Map中; 当执行applicationContext.getBean(beanName)时,从singletonObjects去匹配Bean实例返回
Bean的初始化步骤:
- Bean实例的属性填充(set方法)
- Aware接口属性注入【提供扩展】
- BeanPostProcessor的before()方法回调(----------Bean后处理器的前置方法)
- InitializingBean接口的初始化方法回调
- 自定义初始化方法init回调
- BeanPostProcessor的after()方法回调(------------Bean后处理器的后置方法)
常用Aware接口
Aware接口 | 回调方法 | 作用 |
---|---|---|
ServletContextAware | setServletContext(ServletContext context) | 注入ServletContext对象【Web环境下生效】 |
BeanFactoryAware | setBeanFactory(BeanFacotry factory) | 注入beanFactory对象 |
BeanNameAware | setBeanName(String beanName) | 注入beanName |
ApplicationContextAware | setApplicationContext(ApplicationContext context) | 注入applicationContext对象 |
在初始化第一阶段对属性填充时,对于双向引用属性可能会设计循环依赖问题:
Spring中的循环依赖:类与类直接的依赖关系形成了闭合,如下图所示:
在注入单向对象引用属性时,从容器中getBean获取后通过set方法反射设置进去,如果容器中没 有,则先创建被注入对象Bean实例(完成整个生命周期)后,在进行注入操作;
双向引用可以看作是2个方向的单向引用
上图所示的循环依赖问题:Service实例化对象,接着初始化,需要Dao,容器中没有Dao对象,先去创建Dao,实例化Dao对象,初始化Dao,需要Service,容器中此时也没有Service对象。
解决方案:Spring提供三级缓存存储 完整Bean实例 和 半成品Bean实例 ,用于解决循环引用问题
//1、最终存储单例Bean成品的容器,即实例化和初始化都完成的Bean,称之为"一级缓存" Map<String,Object>singletonObjects = new ConcurrentHashMap(256);
//2、早期Bean单例池,缓存半成品对象,且当前对象已经被其他对象引用了,称之为"二级缓存" Map <String,Object>earlySingletonObjects = new ConcurrentHashMap(16);
//3、单例Bean的工厂池,缓存半成品对象,对象未被引用,使用时在通过工厂创建Bean,称之为"三级缓存" Map<String,ObjectFactory<?> singletonFactories = new HashMap(16);
引入三级缓存后:
- UserService 实例化对象,但尚未初始化,将UserService存储到三级缓存;
- UserService 属性注入,需要UserDao,从缓存中获取,没有UserDao;
- UserDao实例化对象,但尚未初始化,将UserDao存储到到三级缓存;
- UserDao属性注入,需要UserService,从三级缓存获取UserService,UserService从三级缓存移 入二级缓存;
- UserDao执行其他生命周期过程,最终成为一个完成Bean,存储到一级缓存,删除二三级缓存;
- UserService 注入UserDao;
- UserService执行其他生命周期过程,最终成为一个完成Bean,存储到一级缓存,删除二三级缓 存。
三、操作使用:
以上步骤就是Spring框架为我们创建对象的基本过程,此时的Bean可以正常通过我们操作使用就是调用ApplicationContext应用上下文对象getBean()获取“已成型”的Bean对象直接操作即可
四、销毁:
- DisposableBean接口的初始化方法回调:当Bean不再需要时,会警告清理阶段,如果Bean实现了DisposableBean接口,会调用其实现的destory()执行销毁
- 自定义初始化方法destory回调:如果这个Bean的Spring配置中配置了destory-method属性,会自动调用其配置的自定义销毁方法。
最后总结归纳为2道常见面试题:
1、Spring框架中Bean的声明周期?
2、Spring框架如何解决循环依赖?