前置条件,AService属性中依赖了BService,BService属性中依赖了CService,CService属性中依赖了AService。
@Service
public class AService {
@Autowired
private BService bService;
}
@Service
public class BService {
@Autowired
private AService aService;
}
@Service
public class CService {
@Autowired
private AService aService;
}
按照顺序,先初始化AService,执行AService的生命周期
- 将正在创建的bean放入到singletonsCurrentlyInCreation 中,表示该bean正在创建中
- 实例化AService,得到一个对象,放入singletonFactories(三级缓存)中,
- 填充BService属性,先去单例池中查找是否有BService,如果没有,则创建BService
- 填充CServie属性
- 执行初始化前、初始化后
- 初始化后–>AService代理对象
- 将创建好的对象放入到单例池中
执行BService的生命周期
- 将BService添加到singletonsCurrentlyInCreation ,表示该对象正在创建中。
- 填充AService属性
- 先去单例池中查找是否有AService对象,如果有,则直接返回,没有有继续下面步骤。
- 查看singletonsCurrentlyInCreation 集合中是否存在ASerivce,存在则表示出现ASerivce了循环依赖。
- 从earlySingletonObjects 集合中查找,如果有则返回,没有则继续下面步骤
- 从singletonFactories 集合中查找,该集合的value是一个lamda表达式,该表达式会判断该对象是否需要进行aop,如果需要则会返回一个代理对象,如果不需要则返回一个bean的原始对象。将返回的值存入到earlySingletonObjects 集合中。
- 填充其他属性
- 初始化前、初始化后
- 初始化后
- 放入单例池中
执行CService的生命周期
- 将CService添加到singletonsCurrentlyInCreation ,表示该对象正在创建中。
- 填充AService属性
- 先去单例池中查找是否有AService对象,如果有,则直接返回,没有有继续下面步骤。
- 查看singletonsCurrentlyInCreation 集合中是否存在ASerivce,存在则表示出现ASerivce了循环依赖。
- 从earlySingletonObjects 集合中查找。
- 填充其他属性
- 初始化前、初始化后
- 初始化后
- 放入单例池中
单例Bean出现循环依赖可以被解决,原型Bean出现循环依赖无法被解决。
原型Bean由与每次创建都是一个新的Bean对象,之前创建好的Bean对象无法使用,导致属性依赖的Bean对象无法找到,最终导致原型Bean出现循环依赖之后无法被创建。
总结
1、singletonObjects :缓存经过了完整生命周期的bean
2、private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
earlySingletonObjects :缓存未经过完整生命周期的bean,如果某个bean出现了存活依赖,就会提前把这个未经过完整生命周期的bean放入earlySingletonObjects 中,这个bean如果要经过AOP,那么就会把代理对象放入earlySingletonObjects 中,否则就是把原始对象放入earlySingletonObjects ,但是不管怎么杨们就算是代理对象,代理对象所代理的原始对象也是没有经过完整生命周期的,所以放入earlySingletonObjects 我们就可以统一认为是未经过完整生命周期的Bean。
3、private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
singletonFactories :缓存的是一个ObejctFactory,也就是一个Lambda表达式。在每个Bean的生成过程中,经过实例化得到一个而原始对象后,都会提前基于原始对象暴露一个Lambda表达式,并保存到三级缓存中,这个Lambda表达式可能用刀,也可能用不到,如果当前Bean没有出现循环依赖,那么这个Lambada表达式没用,当前bean按照自己的生命周期正常执行,执行完后直接把挡墙bean放入到单例池中,如果当前bean在依赖注入时发现出现了循环依赖(当前正在创建的Bean被其他bean依赖了),则从单机缓存中拿到Lambda表达式,并执行Lamda表达式得到一个对象,并把得到的对象放入二级缓存(如果当前对象需要AOP,那么执行AOP,得到对应的代理对象,如果无需AOP,则直接得到一个原始对象)。
4、earlyProxyReferences:用来记录某个原始对象是否进行过AOP。