一文搞懂 Spring 循环依赖
我们非常重视原创文章,为尊重知识产权并避免潜在的版权问题,我们在此提供文章的摘要供您初步了解。如果您想要查阅更为详尽的内容,访问作者的公众号页面获取完整文章。
一、循环依赖
1.1 什么是循环依赖:循环依赖指的是两个Bean互相依赖,例如AService依赖BService,同时BService依赖AService。
1.2 循环依赖的类型:循环依赖有三种形态:两者互相依赖、三者相互依赖和自我依赖。循环依赖的出现通常表明代码设计上可能存在问题,应该避免。Spring默认帮助处理循环依赖,但无法处理所有类型的循环依赖。
二、循环依赖解决思路
2.1 解决思路:通过引入缓存,如earlySingletonObjects,能够解决一部分循环依赖。这是Spring三级缓存中的二级缓存,存放原始Bean,尚未完成属性设置和依赖注入。
2.2 存在AOP怎么办:针对AOP的情况,Spring引入了三级缓存singletonFactories。它通过Lambda表达式创建对象的代理对象。当发生循环依赖时,实现提前AOP处理,保证依赖的对象是最终的代理对象。
2.3 小结:Spring解决循环依赖通过提前暴露原始对象并提前处理AOP。注意,三级缓存并不能解决所有循环依赖问题,有些情况需要额外配置。
三、特殊情况
3.1 基于构造器注入:如果依赖是通过构造器注入,则会导致循环依赖时报错,因为在创建原始对象时就需要依赖。
3.2 prototype对象:如果循环依赖双方都是prototype作用域,也会失败,因为这种情况下每次需要都会现场创建,无法使用缓存。
3.3 @Async注解:带有@Async注解的Bean产生循环依赖也会出错,因为在创建过程中,还未代理的原始Bean被注入,而后续生成的代理对象与之不同。
四、@Lazy
通过添加@Lazy注解可以解决上述无法自动解决的循环依赖问题。@Lazy注解可以延迟加载,实际上会生成一个代理对象,破解循环依赖。
2. 原理分析:@Lazy注解工作原理是在属性填充时,不立即查找注入的对象,而是提供一个代理对象,在实际需要时再去容器中查找。
想要了解更多内容?
白皮书上线