每一年都奔走在自己热爱里

没有人是一座孤岛,总有谁爱着你

Spring bean创建之循环依赖与三级缓存

Spring bean创建之循环依赖与三级缓存

循环依赖

多个对象之间互相引用形成环

如果使用普通new方法创建,对象之间会循环创建导致OOM

三级缓存
  • 一级缓存:singletonObjects
  • 二级缓存:earlySingletonObjects
  • 三级缓存:singletonFactories

在创建对象时会按照:一级--->二级--->三级的顺序尝试获取对象

bean的创建

对于ClassPathXmlApplicationContext获取bean对象,前置有一系列方法初始化容器、定义BeanFactoryPostProcess、国际化、多播器等的准备工作。

核心对象创建对象方法:

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

堆栈信息:

之后将会循环遍历需要创建bean对象的列表,调用getBean方法

尝试从三级缓存中获取:

获取不到,只能创建对象:

将会调用lambda表达式中的createBean进行对象的创建

到此对象已经实例化完成,需要进行初始化,不过在调用populateBeanff初始化前,将调用addSingletonFactory方法将包含自身实例的objectFactory放入第三级缓存中。

具体的实现方法:

为了解决依赖的对象不存在的问题,同样是依靠getBean方法解决

不过这一次,在第三级缓存中可以获取到循环依赖的对象(假设是两个对象之间循环依赖,开始创建的是A对象,目前创建的是B对象,此时B对象可以从第三级缓存中获取到实例化的A对象,直接装配到B对象中)

此时获取到只实例化的A对象后,将第三级缓存中的A对象移除,放到二级缓存中,值得注意的是B对象在初始化前也会将自己放入三级缓存中,由于自身的依赖已经解决,B对象在getSingleton方法返回前又会将自己的从三级缓存中删除放到一级缓存中。

至此B对象已经初始化完成,只需将属性注入到A中即可,而A对象被初始化完成之后也会将自己从二三级缓存中删除,放入到一级缓存中,至此A对象创建完成。

在for循环遍历下一个需要创建的Bean时,会直接从缓存中获取,不需要再实例化、初始化。

整个过程的堆栈信息:

流程图:

posted @ 2021-06-17 21:43  雨下整夜~  阅读(188)  评论(0)    收藏  举报