当前位置: 代码网 > it编程>编程语言>Java > 什么是Spring循环依赖?如何用三级缓存解决Bean依赖问题?

什么是Spring循环依赖?如何用三级缓存解决Bean依赖问题?

2026年08月04日 Java 我要评论
什么是循环依赖?循环依赖就是spring在初始化bean时两个不同的bean你依赖我,我依赖你的情况例如a依赖b,b依赖a,当ioc容器初始化a时,发现它依赖于b,然后去创建b,创建b的时候又发现b依

什么是循环依赖?

循环依赖就是spring在初始化bean时两个不同的bean你依赖我,我依赖你的情况

例如a依赖b,b依赖a,当ioc容器初始化a时,发现它依赖于b,然后去创建b,创建b的时候又发现b依赖于a,而容器中不存在a,如果不想办法解决,这就会陷入死循环

例如下面这个代码,就是典型的循环依赖

// spring 配置类,启用组件扫描
@configuration
@componentscan
class appconfig {
}

// author 服务类,依赖 bookservice
@service
class authorservice {
    @autowired
    bookservice bookservice;
}

// book 服务类,依赖 authorservice
@service
class bookservice {
    @autowired
    authorservice authorservice;
}

// 程序入口类,测试循环依赖注入
public class springcirculardependencysingleclass {
    public static void main(string[] args) {
        applicationcontext annotationconfigapplicationcontext = new annotationconfigapplicationcontext(appconfig.class);
        bookservice bookservice = (bookservice) annotationconfigapplicationcontext.getbean("bookservice");
        system.out.println(bookservice.authorservice);

        authorservice authorservice = (authorservice) annotationconfigapplicationcontext.getbean("authorservice");
        system.out.println(authorservice.bookservice);
    }
}    

运行这个项目,会发现它是正常运行的,这就表示spring在背后做了一些工作解决了循环依赖的问题

如何解决?

spring是使用三级缓存的模式来解决循环依赖问题的,其实两级缓存也是能够解决一般的循环依赖问题的,三级缓存主要是为了更好的解决带有aop的bean的循环依赖情况

这里先用两级缓存结构来初步阐述思想

采用两级缓存解决

spring解决循环依赖的关键在于巧妙利用缓存机制。在spring的实现中,主要涉及两个重要的map:

  • singletonobjects:这是一个单例池,存放的是经历了完整spring生命周期的bean实例。这些bean的所有依赖都已成功填充,处于完全可用状态。
  • earlysingletonobjects:该map用于存放提前暴露出来的bean对象。这些bean刚刚创建完成,但尚未经历完整的spring生命周期,其依赖尚未填充完毕

假设此时有两个bean分别叫a、b,它们互相依赖

解决循环依赖的具体步骤如下:

  • 1.先创建a的实例对象,在a的依赖注入之前,将a的早期对象放入earlysingletonobjects中去,然后开始给a注入依赖,发现依赖于b(此时两级缓存中都没有b),于是转去创建b
  • 2.创建b的实例对象,将b的早期对象放入earlysingletonobjects,然后给b注入依赖,发现b依赖于a,于是去缓存中查找符合条件的bean
  • 3.先从singletonobjects中查找,发现没有,然后去earlysingletonobjects查找,发现存在a的早期对象,于是返回这个早期对象
  • 4.将a注入到b中,然后将b放入singletonobjects中去
  • 5.这个时候a可以从singletonobjects中获取b的实例,然后将完整的a放入singletonobjects中,循环依赖问题得以解决

需要aop的bean的循环依赖问题?

当一个bean需要使用增强时,我们需要的是它的代理对象而不是它的原型对象,这个时候简单的两级缓存结构并不能很好的解决这个问题,所以spring选择了三级缓存结构来解决

(两级缓存的解决思路是,在将早期对象放入earlysingletonobjects中前,先判断一下该对象是否需要aop,如果需要的话生成该对象的代理对象放入earlysingletonobjects

但是!spring的理念是尽量的把aop的部分放到构造bean的后期解决,而不是上来就直接生成一个代理对象,而且过早的生成代理对象也会额外造成空间和时间的消耗)

三级缓存解决

spring引入了一个新的map singletonfactories 来解决这个问题。

singletonfactories 存放的是 objectfactory 类型的工厂方法。

当创建完对象后,并不立即进行aop增强,而是将获取该对象的工厂方法放入 singletonfactories 。

当发生循环依赖需要获取对象时,如果从 earlysingletonobjects 中无法获取到合适的对象,就从 singletonfactories 中取出工厂方法并执行,从而获取经过aop增强后的对象。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com