生命周期的四个阶段:
1.实例化:Instantiation
2.属性赋值:Populate
3.初始化:Intialization
4.销毁:Destuction
实例化>属性赋值>初始化>销毁
1.实例化bean:反射的方式生成对象
2.填充bean的属性:populate Bean(),循环依赖的问题(三级缓存)
3.调用aware接口的相关方法:invokeAwareMethod(完成BeanName,BeanFactory,Bean Class Loader对象的属性设置)
4.调用BeanPost Processor中的前置处理方法:使用比较多的有(ApplicationContextPostProcessor,设置ApplicationContext,Environment,ResouceLoader等对象)
5.调用initmethod方法:initmethod(),判断是否实现了initaizingBean接口,如果有调用afterPropertiesSet方法,没有就不调用
6.调用BeanPostProcessor的后置处理方法:spring的aop就是在此处实现的,AbstractAutoProxyCreator:钩子函数
注册Destuction相关的回调接口
7.获取到完整的对象,可以通过getBean的方式来进行对象的获取
8.销毁流程,1.判断是否实现了DispoableBean接口,2.调用destroyMethod方法
Spring中如何解决循环依赖问题的?
循环依赖:A依赖B,B依赖A
先说明bean的创建过程:实例化,初始化(填充属性)
1.先创建A对象,实例化A对象,此时A对象中的b属性为空,填充属性b
2.从容器中查找B对象,如果找到了直接赋值不存在循环依赖问题(不通),找不到直接创建B对象
3.实例化B对象,此时B对象中的a属性为空,填充属性a
4.从容器中查找A对象,找不到,直接创建
形成闭环的原因
此时如果仔细琢磨会发现A对象是存在的,只不过此时的A对象不是一个完整的状态,只完成了实例化但是未完成初始化,如果在程序调用过程中,拥有了某个对象的引用,能够在后期给他完成赋值操作,可以优先把非完整状态的对象优先赋值,等待后续操作来完成赋值,相当于提前暴露了某个不完整对象的引用。所以解决问题的核心在于实例化和初始化分开操作,这也是解决循环依赖问题的关键,
当所有的对象都完成实例化和初始化操作之后,还要把完整对象放到容器中,此时在容器中存在对象的几个状态,完成实例化=但未完成初始化,完整状态,因为都在容器中,所以要使用不同的map结构来进行存储,此时就有了一级缓存和二级缓存,如果一级缓存中有了,那么二级缓存就不会存在同名的对象,因为他们的查找顺序是一二三这样的方式查找的。
一级缓存中存放的是完整对象,二级缓存中存放的是非完整对象。三级缓存的value类型是一个ObjectFactory,是一个函数式接口存在的意义是保证在整个容器的运行过程中同名的Bean对象只有一个。