SpringBean的生命周期
- 什么时候创建Bean对象?
- 创建Bean对象的前后都调用了哪些方法?
- Bean对象什么时候被销毁?
- Bean对象销毁前后都调用了哪些方法?
Bean对象的生命周期大致上分为5大步
- 实例化bean
- bean属性赋值
- 初始化bean
- 使用bean
- 销毁bean
需要注意的是:
- 只有正常关闭spring容器,bean的销毁方法才会被调用
- ClassPathXmlApplicationContext类才有close()方法
- 配置文件中init-method指定初始化方法,destory-method指定销毁方法
Bean对象生命周期7步
- 实例化bean
- bean属性赋值
- bean后处理器before方法执行
- 初始化bean
- bean后处理器after方法执行
- 使用bean
- 销毁bean
在以上5步中,第三步是初始化bean,如果你想在初始化前或者初始化后添加代码,可以加入“bean后处理器”
具体实现为:写一个类去实现BeanPostProcessor接口,重写before()和after()方法
需要注意的是,在spring.xml文件中配置的Bean后处理器将作用于当前配置文件中所有的bean
Bean生命周期之十步
- 实例化bean
- bean属性赋值
- 检查bean是否实现了Aware的相关接口,并设置相关依赖
- 当bean实现了BeanNameAware接口,Spring会将Bean的名字传递给bean
- 当bean实现了BeanClassLoaderAware接口,Spring会将加载该Bean的类加载器传递给bean
- 当bean实现了BeanFactoryAware接口,Spring会将Bean工厂对象传递给bean
- bean后处理器before方法执行
- 检查bean是否实现了InitializingBean接口,并调用接口方法
- 初始化bean
- bean后处理器after方法执行
- 使用bean
- 检查bean是否实现了DisposableBean接口,并调用接口方法
- 销毁bean
Bean的作用域不同,管理方式也不同
- 对于singleton(单例)作用域的bean来说,Spring精确的知道该bean何时被创建,何时初始化完成,以及何时被销毁
- 对于prototype(原型)作用域的bean来说,Spring只负责创建,当容器创建了Bean的实例后,bean的实例就交给客户端代码管理,Spring容器不再跟踪其生命周期。
自己new的对象怎么交给Spring进行管理
//创建对象
User user=new User();
//创建默认可列表BeanFactory对象
DefaultListableBeanFactory factory=new DefaultListableBeanFactory();
//注册Bean
factory.registerSingleton("userBean",user);
//从容器中获取bean
User userBean=factory.getBean("userBean",User.class);
Spring是如何解决Bean的循环依赖问题的
什么是循环依赖==》A对象中有B属性。B对象中有A属性,这就是循环依赖
什么情况下Spring能够解决bean的循环依赖?
-
在singleton+set方法注入的情况下
-
在一个为prototype与一个为singleton的情况下也可以解决
-
singleton+构造方法注入就是不能解决的会报BeanCurrentlyInCreationException 异常
- 主要原因是因为构造方法注入导致的,构造注入会导致实例化对象的过程和对象属性赋值的过程没有分离开。在一起完成导致的
Spring为什么能解决循环依赖的原理
spring为什么能解决set+singleton模式下的循环依赖呢?
根本原因在于:在这种方式可以做到将“实例化bean”和“给bean赋值”这两个动作分开去完成。实例化bean的时候调用无参构造方法来完成。此时可以先不给属性赋值,可以提前将该bean对象“曝光”给外界。给bean属性赋值的时候调用setter方法来完成。两个步骤可以完全分开去完成的,并且这两部不要求在同一时间点上来完成。也就是说bean是单例的,我们先把所有的单例bean实例化出来,放到一个集合中(我们称之为缓存),所有的单例bean全部实例化完成之后,以后我们再慢慢调用set方法给属性赋值,这样就可以解决循环依赖的问题。
从spring源码中我们可以得到spring创建三个map作为单例bean的缓存。spring会先从一级缓存中获取bean。如果获取不到就从二级缓存中获取。如果获取不到,就从三级缓存中获取之前曝光的ObjectFactory对象,通过ObjectFactory对象获取bean实例,这样就解决了循环依赖的问题。
Cache of singleton objects: bean name to bean instance. 单例对象的缓存:key存储bean名称,value存储Bean对象【一级缓存】
Cache of early singleton objects: bean name to bean instance. 早期单例对象的缓存:key存储bean名称,value存储早期的Bean对象【二级缓存】
Cache of singleton factories: bean name to ObjectFactory. 单例工厂缓存:key存储bean名称,value存储该Bean对应的ObjectFactory对象【三级缓存】
这三个缓存其实本质上是三个Map集合。
我们再来看,在该类中有这样一个方法addSingletonFactory(),这个方法的作用是:将创建Bean对象的ObjectFactory对象提前曝光。
-