spring-spring循环依赖&三级缓存

文章详细解释了Spring框架中的三级缓存如何解决循环依赖问题。在填充bean属性过程中,如果遇到循环依赖,Spring会利用三级缓存(singletonObjects、earlySingletonObjects、singletonFactories)来避免死循环,确保正确实例化对象。此外,文章还提出了对循环依赖产生的原因和递归调用的思考,并提出了不同的设计策略。
摘要由CSDN通过智能技术生成

spring循环依赖&三级缓存

三级缓存

想来大家面试的时候,都被问到过三级缓存以及循环依赖,那么三级缓存到底是什么,又解决了什么问题呢
下面来看看三级缓存

三级缓存解释

singletonObjects : 存放最终生成的单例对象
earlySingletonObjects : 存放早期的对象,也就是A、B循环依赖的时候,先生成的那个不完成的bean
singletonFactories : 存放FactoryBean生成的对象

观点

其实三级缓存也好,二级或者一级缓存也好,都能解决循环依赖的问题,也能解决spring容器关于存放生成的实例bean的问题
因为spring有存beanDefinition,而在beanDefinition中对于bean有详细的描述,所以一级缓存也行
但是,三级缓存逻辑更清晰,不管是开发spring的也好,读源码的也好,都不会有太多的混乱

循环依赖

有以下两个程序,可以明显看到是循环依赖的代码
HelloWorld.java

@Slf4j
@Component
public class HelloWorld {
    @Autowired
    private Person person;
    public void sayHello(){
        log.info("say hello");
    }
}

Person.java

@Slf4j
@Component
public class Person {
    @Autowired
    private HelloWorld helloWorld;
    public void eat(){
        log.info("eat");
    }
}
解决循环依赖

那么,spring容器又是怎么去解决循环依赖的问题呢,看下图
循环依赖核心代码

  1. 要填充Person的过程中,发现有个属性是Helloworld,需要实例化Helloworld
  2. 在填充Helloworld过程中,发现有个属性是Person,但是Person已经实例化好了,就把Person放到earlySingletonObjects
  3. 取Person对象时,发现singletonObjects中没有,于是就去earlySingletonObjects中找
  4. 找到Person对象后,把Person对象填充到Helloworld对象中,并在earlySingletonObjects中删除Person对象
  5. 把Helloworld对象放到singletonObjects,然后填充Person对象中的Helloworld
  6. 把Person对象放到singletonObjects
    总结一下:
    循环依赖问题是由于A、B类相互引用,然后在填充对象的过程中,singletonObjects找不到对象,就会一直去创建,所以才会死循环
    解决死循环的方法就是,把A类或者B类没有填充属性的对象暂存起来,那么在填充对象时找到相应的对象,就会跳出循环

关于循环依赖的一些看法

  1. 造成循环依赖的究极原因是循环调用,在一些中间件中,代码写的也不是那么高大上
  2. 特别是国外的一些程序员,最喜欢用递归,比如mybtis中filter的调用,tomcat中filter的执行,都存在递归调用
  3. 递归有递归的好处,递归存在代码量少的优点,但是非常容易出问题
  4. 关于循环依赖,在我看来还有另外一种设计
    1) spring在扫描类之后,需要生成的单例bean的数据已经确定,产生循环依赖的问题实在填充属性的时候,
    2) 使用for循环进行单例bean的生成,只不过是没有填充属性
    3) 使用for循环进行属性填充,效率高,不容易产生问题
  5. 有可能springIOC的作者在写第一版的时候,就用了递归,但是后来遇循环依赖问题的时候,只是对问题进行修改,没有对代码进行重构,所以才有了我们今天看到的代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值