注入方式分类:
构造注入: 直接抛异常,无法解决,bean池
setter注入: 可以实现,利用三级缓存
非单例注入: 无法实现,未缓存
spring单例对象的创建过程:
createBeanInstance:实例化,其实也就是调用对象的构造方法实例化对象
populateBean:填充属性,这一步主要是多bean的依赖属性进行填充
initializeBean:调用spring xml中的init 方法。
构造器循环依赖
当我们实例化bean的时候,会将正在创建的bean加入到当前创建bean 池中,创建过程中会一直保存在这个池中,如果进行对象实例化的时候,发现缓存池里面已经存在,就会抛异常
setter注入
采用三级缓存,在实例完成后,没有初始化之前,暴漏bean.
三级:基于单例工厂的缓存,进入实例化阶段的缓存.singletonFactories
二级:实例化之后,没初始化之前,提前暴光的单例对象的Cache
三级: singletonObjects:完成初始化的单例对象的cache(一级缓存)
在利用构造器实例化bean后,提前报露出来,供使用,好处?
A实例化阶段放入三级缓存,提前暴漏->依赖B->实例化B->初始化->发现依赖->三级缓存获取A->B初始化完成->B放一级缓存->A初始化依赖B完成
当A对象实例化后,放到singletonFactories 里面.然后进行初始化,发现自己依赖B,发现B还没有被create
就去创建B,创建B,首先实例化B,实例化B,之后进行初始化,发现依赖A,就会从一级缓存singletonObjects获取(没有,A还没有初始化)
,之后尝试从二级缓存earlySingletonObjects获取,也没有,尝试从三级缓存获取,由于A实例化阶段在三级缓存暴漏,
这样就get到了A.(ObjectFactory.getObject),B拿到A对象后,就完成自己的初始化,然后将自己放进一级缓存.
这样B就完成了创建,然后返回到A中,A能从一级缓存中获取到B,顺利完成自己的初始化,之后,把自己放进一级缓存.
由于B对象前期初始化的时候拿到了A的引用,所以现在B中获取的A也完成了初始化
非单例循环依赖?
非单例的bean,在创建的时候没有进行缓存,无法提前暴漏,无法完成循环依赖