Spring如何解决循环依赖问题

前置条件,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的生命周期

  1. 将正在创建的bean放入到singletonsCurrentlyInCreation 中,表示该bean正在创建中
  2. 实例化AService,得到一个对象,放入singletonFactories(三级缓存)中,
  3. 填充BService属性,先去单例池中查找是否有BService,如果没有,则创建BService
  4. 填充CServie属性
  5. 执行初始化前、初始化后
  6. 初始化后–>AService代理对象
  7. 将创建好的对象放入到单例池中

执行BService的生命周期

  1. 将BService添加到singletonsCurrentlyInCreation ,表示该对象正在创建中。
  2. 填充AService属性
    1. 先去单例池中查找是否有AService对象,如果有,则直接返回,没有有继续下面步骤。
    2. 查看singletonsCurrentlyInCreation 集合中是否存在ASerivce,存在则表示出现ASerivce了循环依赖。
    3. 从earlySingletonObjects 集合中查找,如果有则返回,没有则继续下面步骤
    4. 从singletonFactories 集合中查找,该集合的value是一个lamda表达式,该表达式会判断该对象是否需要进行aop,如果需要则会返回一个代理对象,如果不需要则返回一个bean的原始对象。将返回的值存入到earlySingletonObjects 集合中。
  3. 填充其他属性
  4. 初始化前、初始化后
  5. 初始化后
  6. 放入单例池中

执行CService的生命周期

  1. 将CService添加到singletonsCurrentlyInCreation ,表示该对象正在创建中。
  2. 填充AService属性
    1. 先去单例池中查找是否有AService对象,如果有,则直接返回,没有有继续下面步骤。
    2. 查看singletonsCurrentlyInCreation 集合中是否存在ASerivce,存在则表示出现ASerivce了循环依赖。
    3. 从earlySingletonObjects 集合中查找。
  3. 填充其他属性
  4. 初始化前、初始化后
  5. 初始化后
  6. 放入单例池中

单例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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值