这里是自己的理解,免得以后忘记了。如果理解有误,请指出。一、背景在写代码的过程中,我们一般会使用@Autowired来注入另一个对象,但是有时候会出现循环依赖,而我们的代码却不报错。这是什么原因?二、前置知识1、考虑循环依赖的类型。这里考虑单例+@Autowired的循环依赖,不考虑使用构造函数注入或原型作用域注入bean。2.什么时候创建代理对象注意:一般情况下,也就是没有循环依赖的时候,aop增强是在bean初始化完成后的BeanPostProcessor#postProcessAfterInitialization方法中,但是如果有循环依赖,就需要要在getEarlyBeanReference中提前创建Proxy对象。3、三级缓存中保存的是什么对象?缓存字段名,缓存级别,数据类型解释,singletonObjects1Map保存的是一个完整的Bean,也就是早期可以使用的BeanSingletonObjects2Map保存的是一个半成品的Bean,也就是属性还没有还没有设置好,初始化工作还没有完成。singletonFactories3Map>主要是生成bean,然后放到二级缓存中注意:每次调用ObjectFactory#getObject()都会生成一个新的对象或者返回旧的对象.对象,取决于代理是否存在等。4.从三级缓存中获取对象org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String,boolean));实例化Bean,即newBean()2.加入三级缓存addSingletonFactory(beanName,()->getEarlyBeanReference(beanName,mbd,bean));添加到三级缓存是通过一些条件判断的,一般会成立,这里认为需要添加到三级缓存。3.设置bean的属性populateBean(beanName,mbd,instanceWrapper);第一步是实例化bean,但是此时并没有填充需要注入的属性,通过这一步来填充属性。4.初始化beanObjectexposedObject=initializeBean(beanName,exposedObject,mbd);初始化Bean,执行初始化方法,Aware回调,执行BeanPostProcessor#postProcessAfterInitialization方法(aop的增强就是在这里面实现的),如果有循环引用,那么aop的Enhancements需要提前。5.添加到一级缓存addSingleton(...)3.理解@ComponentclassA{@AutowiredprivateBb;}@Transaction(proxyexists)@ComponentclassB{@AutowiredprivateAa;}1.假设只有singletonObjects和earlySingletonObjects可以完成循环依赖缓存字段名缓存级别数据类型说明singletonObjects1Map保存完整的Bean,即可以使用earlySingletonObjects2Map保存半成品Bean,即就是,属性还没有设置,初始化工作还没有完成。这时需要获取B的实例,即getBean("b")。从上面学习Bean的简化过程,我们从上图可以看出,当对象有代理时,二级缓存是解决不了问题的。因为代理对象是通过BeanPostProcessor完成的,是设置属性后生成的代理对象。这时候可能有人会说了,如果我把B的实例建好之后马上进行Aop代理,这不就解决问题了吗?假设A和B之间没有循环依赖,这样设计会不会不够优雅?2.假设只有singletonObjects和singletonFactories才能完成循环依赖,从图中可以看出也是无法实现的。三、如何实现三级缓存1、解决代理问题因为默认情况下,代理是通过BeanPostProcessor来完成的。为了解决代理,需要提前创建代理,然后将代理的创建放在三级缓存中进行创建。addSingletonFactory(beanName,()->getEarlyBeanReference(beanName,mbd,bean));getEarlyBeanReference该方法会返回代理bean2,解决通过三级缓存多次获取单例值不一致的问题。从上图可以看出,对象是先从Level1->Level2->Level3缓存中通过这种方式搜索得到的。当对象在三级缓存中产生后,会缓存到二级缓存中,同时删除三级缓存。三、流程图四、总结1、一级缓存singletonObjects存放可以使用的单例对象。2、二级缓存earlySingletonObjects存放的是earlyBeans,是半成品,此时还不能使用。3、三级缓存singletonFactories是一个对象工厂,用来创建对象,然后放入二级缓存。同时,如果对象有Aop代理,对象工厂返回代理对象。创建的代理对象可以直接存放在earlySingletonObjects中吗?这样可以解决问题,但设计未必合理。因为在Spring中,Aop的代理是在对象完成后创建的。而如果没有循环依赖,是否需要提前创建代理对象呢?分为三级缓存,代码结构更加清晰合理。