Spring如何解决循环依赖问题

一、循环依赖

        什么是循环依赖:它发生在bean A依赖于另一个bean B时,bean B依赖于bean A;

简单讲就是,类和类之间的依赖关系产生了闭环,就会导致循环依赖问题的发生。

        具体代码如下:

@Bean
public class A {
    @Autowire
    private B b;
}
 
 
@Bean
public class B {
    @Autowire
    private C c;
}

@Bean
public class C {
    @Autowire
    private A a;
}


二、发生循环依赖时,Spring会发生哪些情况

        当Spring加载bean时,会按照我们的工作需要进行对Bean的创建,例如:

                beanA ----> beanB---->beanC

        先创建beanC,之后再创建beanB,最后再创建beanA,当beanB创建完成后将其注入beanC中,beanA创建好之后将其注入beanB中。

        但当存在循环依赖时,Spring因不知道先创建哪一个bean,因此会产生循环依赖问题的发生。所以会引发BeanCurrentlyInCreationException异常。

三、Spring如何解决循环依赖问题

Spring通过三级缓存解决了循环依赖的问题;

Spring内部有三级缓存:

        1.singletonObjects 一级缓存,用于保存实例化、注入、初始化完成的bean实例

        2.earlySingletonObjects 二级缓存,用于保存实例化完成的bean实例

        3.singletonFactories 三级缓存,用于保存bean创建工厂,以便于后面扩展有机会创建代理对象。

当类与类之间需要循环引用时:

        1.在A进行实例化以后,使用A实例化后的对象去创建一个对象工厂,将其添加至三级缓存当中,表示A已经进行实例化了;

        2.当A注⼊属性时,发现依赖B,B未被创建,所以去实例化B,当B注入属性时,发现同样C未被创建,再去实例化C;

        3.当C注入A时,它就会从缓存里找A对象。依次从⼀级到三级缓存查询A,从三级缓存通过对象⼯⼚拿到A,发现A虽然不太完善,但是存在,把A放⼊⼆级缓存,同时删除三级缓存中的A,此时,C已经实例化并且初始化完成,把C放入⼀级缓存,A注入B,B注入C也是这样进行的;

        4.接着A继续属性赋值,顺利从⼀级缓存拿到实例化且初始化完成的B对象,同理B也从一级缓存拿到实例化且初始化完成的C对象,A对象创建也完成,删除⼆级缓存中的A,同时把A放⼊⼀级缓存;

        5.最后,⼀级缓存中保存着实例化、初始化都完成的A、B、C对象。

        Spring之所以能解决setter注入的循环依赖,时因为实例化和属性赋值是分开的,所以里面有操作的空间。如果都是构造器注入的化,那么都得在实例化这一步完成注入,所以自然是无法支持了。

四、二级缓存为什么不能解决循环依赖问题

        因为往二级缓存中放一个普通的Bean对象,Bean在初始化时,会通过BeanPostProcessor 去⽣成代理对象,之后会覆盖掉二级缓存中的普通Bean对象,会导致读取的Bean不一致。

        而三级缓存中放的是生成对象的匿名内部类,在获取Object时,既可以生成代理对象,也可以返回普通对象。保证使用的是同一个Bean对象。

        以上是对Spirng解决以来循环问题见解,与君共勉!

### Qwen2.5 14B Model Details and Specifications The Qwen2.5 14B model is a large-scale language model designed to handle various tasks with high efficiency and accuracy. It consists of approximately 14 billion parameters, which contribute significantly to its robust performance across multiple domains such as natural language understanding, code generation, and more[^1]. This particular variant within the Qwen series focuses on enhancing capabilities specifically tailored for coding purposes while maintaining strong general-purpose linguistic skills. By leveraging advanced training techniques alongside extensive datasets encompassing both textual information and programming languages examples, it achieves superior results when generating or assisting developers during software development processes. For deployment using Ollama—a lightweight framework optimized for running LLMs (Large Language Models)—one can execute commands like `ollama run qwen2.5-coder` after ensuring that all necessary configurations are properly set up according to official documentation guidelines provided by respective repositories hosting these models' binaries. Additionally, here’s an example demonstrating how one might interact programmatically through Python bindings: ```python import requests url = 'http://localhost:11434/api/generate' payload = { "model": "qwen2.5-coder", "prompt": "def factorial(n):" } response = requests.post(url, json=payload).json() print(response['response']) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值