spring 如何解决循环依赖问题 您所在的位置:网站首页 springboot依赖报错 spring 如何解决循环依赖问题

spring 如何解决循环依赖问题

2023-03-04 17:37| 来源: 网络整理| 查看: 265

什么是循环依赖

很简单, 就是A依赖B, B依赖A. 比如

class A { private B b; } class B { private A a; }

这是问题么? 当然不是, 这个完全可以在构造完对象后设置对应的属性, 像这样:

A a = new A(); B b = new B(); a.setB(b); b.setA(a);

那么下面这个呢.

class A { private B b; public A (B b) { this.b = b; } } class B { private A a; public B (A a) { this.a = a; } }

这是问题么? 当然是, 构造A对象必须使用B对象, 但是构造B对象必须使用A对象, 所以导致两个对象无法创建成功.

分析下两种情况, 第一种情况对象的构造和属性设置分开进行, 而第二种对象的构造和属性设置耦合在一起. 所以本文将第一种情况称为弱依赖, 第二种称为强依赖.

从上述代码可以知道循环依赖如果是强依赖无法解决, 弱依赖才可以处理.

那么spring可以帮助我们解决强依赖么? spring这么强大, 那当然是不行的... spring只是工具不是魔法, 它只是简化工作量而已.

所以spring只能帮我们自动解决弱依赖问题.

spring 如何解决循环依赖

先让大家看下spring解决循环依赖的秘籍~

A a = new A(); B b = new B(); a.setB(b); b.setA(a);

......

不管你信不信, 这就是spring处理循环依赖的思路.

先创建对象. 放到一边备用. 拿出对象并设置属性.

spring会将构造完毕的对象放入一个缓存中等待用户使用, 这个缓存成为一级缓存. 一级缓存存储的都是可以直接使用的对象. 那么哪里存储没有构造完毕的对象(就叫原始对象吧)呢? 那就再加一个缓存, 称为二级缓存, 二级缓存存储原始对象, 还没有构造完毕, 不能提供给用户使用.

整理流程如下:

image.png 三级缓存

如果看spring源码会发现情况要比上述复杂的多, 把握整体思想: 一级缓存存储可使用的对象, 二级缓存存储未完成对象.

三级缓存用于存储对象的工厂方法, 当对象被AOP增强后, 会通过三级获取工厂方法生成增强后的代理对象, 然后将代理对象存储到二级缓存, 并删除三级缓存对应的缓存.

BeanPostProcessor

通过实现BeanPostProcessor可以修改创建的对象, 那对循环依赖会有影响么? 是的, 会影响. BeanPostProcessor可以在对象实例化之后更改创建的对象, 比如在BeanPostProcessor中修改B对象, 那么会在执行后将新的对象注入到A对象中, 如果至此结束则没有问题, 但是如果还要在BeanPostProcessor中修改A对象, 那spring会报错, 因为新提供的A对象不是之前注入到B对象中的对象, 如果注入成功会造成依赖的对象不一致的情况.

原型模式

上面提到的各种缓存都是直接使用缓存中的对象, 如果是原型模式, 每次都需要新建对象的话怎么处理循环依赖? 答案是不能处理...spring会直接报错.

总结 spring只能处理循环依赖为弱依赖的情况. 而且需要是单例模式下. 处理思路就是将依赖双方中间设置一个缓存. 尽量不要出现循环依赖, 2.6以上版本的spring boot默认不支持循环依赖, 出现循环依赖, 就算是弱依赖也会报错, 需要设置spring.main.allow-circular-references配置为true.

本文主旨是理解思想, 如有不对, 欢迎指正 ~



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有