深入了解循环依赖!!!

举个例子

@Component
public class A {
    // A中注入了B
    @Autowired
    private B b;
}
​
@Component
public class B {
    // B中也注入了A
    @Autowired
    private A a;
}
​

上面这种现象产生了循环依赖

1.什么情况下循环依赖可以被处理?

在回答这个问题之前首先要明确一点,Spring解决循环依赖是有前置条件的

  1. 出现循环依赖的Bean必须要是单例

  2. 依赖注入的方式不能全是构造器注入的方式(很多博客上说,只能解决setter方法的循环依赖,这是错误的)

关于循环依赖的解决方式应该要分两种情况来讨论?

  1. 简单的循环依赖(没有AOP)

  2. 结合了AOP的循环依赖

img

首先按照顺序创建A的过程实际上就是调用getBean方法,这个方法有两层含义

1.创建一个新的Bean 2.从缓存中获取到已经被创建的对象

我们现在分析的是第一层含义,因为这个时候缓存中还没有A调用getSingleton(beanName) 首先调用getSingleton(a)方法,这个方法又会调用getSingleton(beanName, true)

public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}

getSingleton(beanName, true)这个方法实际上就是到缓存中尝试去获取Bean,整个缓存分为三级

  1. singletonObjects,一级缓存,存储的是所有创建好了的单例Bean

  2. earlySingletonObjects,完成实例化,但是还未进行属性注入及初始化的对象

  3. singletonFactories,提前暴露的一个单例工厂,二级缓存中存储的就是从这个工厂中获取到的对象

A在创建过程中需要B,于是A先将自己放到三级缓存里面,去实例化B

B实例化的时候发现需要A,于是B先查一级缓存,没有再查二级缓存,还是没有,再查三级缓存,找到了A;然后把三级缓存里面的这个A放到二级缓存里面,并删除三级缓存里面的A

B顺利初始化完毕,将自己放到一级缓存里面(此时B里面的A依然是创建中状态);然后回来接着创建A,此时B已经创建结束,直接从一级缓存里面拿到B,然后完成创建,并将A放入到一级缓存中


 

二级缓存行不行,为什么用三级缓存呢?

二级可以,对于创建的bean不需要AOP代理的对象二级缓存是可以的

但是如果有代理对象,则不行

因为我们期望的注入的是一个被代理后的对象,而不是一个原始对象! 所以这里并不能够直接将一个原始对象放置到缓存中,我们可以直接进行判断(就是用 objectFactory实际上就是一个对应的lamba表达式),如果需要Aop的话进行代理之后放入缓存!

但是Aop的操作是在哪里做的?

是在Spring声明周期的最后一步来做的!如果我们进行判断创建的话,Aop的代理逻辑就会在创建实例的时候就进行Aop的代理了,这明显是不符合Spring对于Bean生命周期的定义的! 所以,Spring重新定义了一个缓存 singletonFactories 用来存放一个Bean的工厂对象,创建的对象之后,填充属性之前会把创建好的对象放置到 singletonFactories 缓存中去,并不进行实例化,只有在发生了循环引用,或者有对象依赖他的时候,才会调用工厂方法返回一个代理对象,从而保证了Spring对于Bean生命周期的定义!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值