if (earlySingletonExposure) { //默认为true
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//把ObjectFactory存到三级缓存中,三级缓存中的Bean会被后置处理来增强:代理等
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
.....
//给创建好的对象每个属性进行赋值,@Autowired发生在这里
populateBean(beanName, mbd, instanceWrapper);
//初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
.....
说明:
- 上述代码是doCreateBean()里面的代码:首先默认将bean对应的ObjectFactory存入三级缓存中,然后属性赋值,初始化。
- 一级缓存存放成品bean的实例,二级缓存存放半成品bean,三级缓存存放ObjectFactory,可以在调用相应的方法时返回bean,其中二级缓存和三级缓存是专门来解决循环依赖的问题的。
原因:
- 解决循环依赖需要提前暴露半成品bean。
- 如果只有一级三级缓存,连半成品bean都没有,何从谈起解决循环依赖之说。
- 如果只有一级二级缓存,为了解决循环依赖,需要先将半成品bean存到二级缓存中暴露出来,但是又为了解决代理问题,暴露出来的bean还得是代理后的,所以需要此时(刚实例化bean后)就生成代理对象,否则:就会出现b中注入的a不是代理a的情况,但是spring设计之初是在bean初始化最后阶段代理,而不是在实例化后马上代理,所以加了三级缓存来延迟生成代理对象,这样只有在循环依赖这种情况下不得不用到bean的时候才生成代理bean并返回,没有循环依赖就不会生成代理bean,所以就保证了绝大多数情况还是会在初始化最后阶段生成代理对象。
总结:
其实笔者认为:spring用几级缓存无所谓,用几级都可以实现,只不过是spring做了一些取舍,最终用了三级,
如果把一二级缓存合成一个,#beanname表示成品bean,%beanname表示半成品bean,也是一样可以实现的,
只不过是丑陋、不太合理一点。
欢迎大家在评论区提出问题讨论,笔者看到会第一时间回复,如果觉得对你有帮助的话就点个赞吧。