Spring是怎么解决循环依赖的?

什么是循环依赖?

  • 通俗的讲就是N个bean相互引用对方,最终形成闭环。

循环依赖会产生什么问题?

  • Bean无法成功注入,导致业务无法进行
  • 产生死循环

Spring中解决循环依赖的方式?

  • 使用注解@Lazy


    image.png
  • setter方式注入


    image.png
  • @PostConstruct


    image.png
  • 实现ApplicationContextAware与InitializingBean


    image.png

Spring整个解决循环依赖问题的实现思路

  • Spring是通过递归的方式获取目标bean及其所依赖的bean的;
  • Spring实例化一个bean的时候,是分两步进行的,首先实例化目标bean,然后为其注入属性。
    结合这两点,也就是说,Spring在实例化一个bean的时候,是首先递归的实例化其所依赖的所有bean,直到某个bean没有依赖其他bean,此时就会将该实例返回,然后反递归的将获取到的bean设置为各个上层bean的属性的。

Spring二级缓存可以解决循环依赖吗?

1. 一级缓存能解决吗?

只有一级缓存并不是不能解决循环依赖。因为 A 的成品创建依赖于 B,B的成品创建又依赖于 A,当需要补全B的属性时 A 还是没有创建完,所以会出现死循环。

2. 二级缓存能解决吗?

有了二级缓存已经能解决循环依赖了。一个缓存用于存放成品对象,另外一个缓存用于存放半成品对象。A 在创建半成品对象后存放到缓存中,接下来补充 A 对象中依赖 B 的属性。B 继续创建,创建的半成品同样放到缓存中,在补充对象的 A 属性时,可以从半成品缓存中获取,现在 B 就是一个完整对象了,而接下来像是递归操作一样 A 也是一个完整对象了。

3. 三级缓存解决什么?

有了二级缓存都能解决 Spring 依赖了,怎么要有三级缓存呢。其实我们在前面分析源码时也提到过,三级缓存主要是解决 Spring AOP 的特性。AOP 本身就是对方法的增强,是 ObjectFactory<?> 类型的 lambda 表达式,而 Spring 的原则又不希望将此类类型的 Bean 前置创建,所以要存放到三级缓存中处理。其实整体处理过程类似,唯独是 B 在填充属性 A 时,先查询成品缓存、再查半成品缓存,最后在看看有没有单例工程类在三级缓存中。最终获取到以后调用 getObject 方法返回代理引用或者原始引用。至此也就解决了 Spring AOP 所带来的三级缓存问题。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容