目录
1、举例:AServiec依赖BService,BService依赖AService
一、循环依赖
1、循环依赖:很简单,就是A依赖B,B依赖A。
2、问题:在Spring中循环依赖就是一个问题了,因为在Spring中,一个对象并不是简单的new出来的,而是会经过一系列的Bean的生命周期,就是因为Bean的生命周期,所以才会出现循环依赖问题。
二、解决循环依赖的思路
如何打破这个循环,加入三级缓存。
1、举例:AServiec依赖BService,BService依赖AService
先创建AService,执行AService的生命周期
0、creatingSet<AService>,纪录是否开始创建AService对象的动作;
1、实例化Aservice--->得到一个对象--->singletonFactories<AService,lambda<AService原始对象>>;
2、填充BService属性--->去单例池中寻找BService--->Map--->没有则创建BService;
3、初始化前、初始化;
4、初始化后;
5、放入单例池。
创建BService,执行BService的生命周期
0、实例化BService--->得到一个对象--->Map<BService,BService原始对象>;
1、填充AService属性--->去单例池中找AService--->creatingSet--->出现了循环依赖--->earlySingletonObjects--->sigletonFactories--->lambda--->执行;
2、填充其他属性;
3、初始化前、初始化;
4、初始化后;
5、放入单例池。
2、循环依赖的打破
真正打破循环依赖的是三级缓存,在实例化AService后,得到一个对象,会往singletonFactories<AService,lambda<AService原始对象>>,在创建BService中填充AService属性时,在单例池中没找到AService,通过CreatingSet发现出现了循环依赖,然后会去二级缓存中寻找,二级缓存中没有找到,则在三级缓存中一定能找到,不然如果没找到就需要重新创建AService这样就又是循环依赖了肯定不合理。三级缓存也决定了二级缓存中的对象是原始对象还是代理对象。
三、三级缓存解析
1、三级缓存的通常叫法:
①、一级缓存:sigletonObjects
②、二级缓存:earlySingletonObjects
③、三级缓存:sigletonFactories
2、三级缓存详情
①、sigletonObjects:缓存经过了完整生命周期的bean;
②、earlySingletonObjects:缓存未经过完整生命周期的bean;
③、sigletonFactories:缓存的是一个ObjectFactory,也就是一个lambda表达式。在每个Bean的生成过程中,经过实例化得到一个原始对象,都会提前基于原始对象暴露一个lambda表达式,并保存到三级缓存中。sigletonObjects中,如果当前bean在依赖注入时发现出现了循环依赖,则从三级缓存中拿到lambda表达式,并执行lambda表达式得到一个对象,并把得到的对象放入二级缓存。如果当前Bean需要AOP,那么执行的lambda表达式,得到的就是对应的代理对象,如果无需AOP,则直接得到一个原始对象。