Spring中循环依赖和三级缓存

前言:

我们首先要知道循环依赖和三级缓存是并存的,也就是说三级缓存就是为了解决循环依赖而存在的。

1.什么是循环依赖

        循环依赖的意思是Spring中的某个Bean在创建过程中需要用到的依赖也需要用到自身(两个或者多个Bean之间相互持有对方的引用),依赖情况分为三种,相互依赖,三者间依赖,自我依赖。

        Bean的创建主要分为两步,一是创建原始对象,二是填充对象属性和初始化;

        我们这里说到的循环依赖就是两个Bean都只能创建出原始对象,无法依赖注入,永远卡在填充对象属性这一步。如下,两个Bean陷入循环依赖。

2.使用缓存解决循环依赖

情景设想:我们是否可以在中间加一个缓存层,将创建好的但是还没有实现注入的的Bean放到一个缓存中,在需要使用到某个Bean的原始对象的时候就进缓存里面找一下看看有没有;

例如:我们创建好了A的原始对象,将它放在缓存中后,B在创建过程中要用到A的话,就可以从缓存中取出,这样B就能完成创建了,Spring还会扫描一遍这个缓存容器中的实例,就可以被依次创建出来,就好比多米诺骨牌效应一样,后面其他Bean也可以被创建出来了。

2.1 为什么要用到二级缓存

上面这个缓存看似已经解决了循环依赖问题,但是还有一个问题,就是这个缓存里面可能会同时存在未完成注入的Bean和已完成赋值的Bean,它们存在一个容器中,调用者就可能会拿到未完成赋值的Bean,就会出现异常(如NullPointerException)和错误,因此二级缓存应运而生,完成了一个分类的功能。

一级缓存:Spring中将能提供给用户使用的Bean放到一级缓存中(称为成熟Bean),一级缓存中的Bean可以直接使用;

二级缓存:像我们上面这种情况的Bean(也就是只进行到一半卡在循环依赖的Bean)放在二级缓存中(称为临时Bean),这里面的Bean主要是用于解决循环依赖问题的,Bean创建和填充属性过程中要用到的Bean可以从里面获取;

2.2为什么要用到三级缓存

在Spring中有许多注入的Bean需要使用到代理Bean(如通过getBean获取Bean的时候),三级缓存中存的是 ObjectFactory<?> 类型的代理工厂对象,用于处理存在 AOP 时的循环依赖问题。

三级缓存的作用是为了解决spring中Bean依赖注入时发生的循环依赖。

如果不需要AOP,那么只需要二级缓存即可实现;

如果有AOP,其实二级缓存也能够实现,但是会打破Bean的生命周期,不符合spring的原则,因为需要把AOP对象放入二级缓存中(这句话好好读读!!),那么就必须在所有需要AOP处理的Bean对象初始化之前对就Bean对象进行后置处理(生成AOP对象),即使没有发生循环依赖!这并不是spring想看到的,所以spring引入了三级缓存,

而且存入的是<beanName, ObjectFactory>结构,ObjectFactory是一个lambda表达式,相当于一个回调函数,当发生循环依赖的时候,会进行lambda表达式的执行,获取到Bean对象或者 AOP代理对象,再将Bean对象或者 AOP代理对象存入二级缓存中,

如果之后还有循环依赖指向该对象(类似 A 依赖 B , B 依赖 A和C , C 依赖 A这种情况),就直接从二级缓存里面获取,从而解决了循环依赖。

这里解释了为什么不直接在二级缓存里存放lambda表达式,因为同一个lambda表达式每执行一次,就会生成一个新的代理对象,不能保证单例。

此段为引用-->原文链接:https://blog.csdn.net/weixin_43475992/article/details/129911318

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值