什么是循环依赖?
举个例子
/**
* A 类,引入 B 类的属性 b
*/
public class A {
private B b;
}
/**
* B 类,引入 A 类的属性 a
*/
public class B {
private A a;
}
复制代码
再看个简单的图:
像这样,创建 a 的时候需要依赖 b,那就创建 b,结果创建 b 的时候又需要依赖 a,那就创建 a,创建 a 的时候需要依赖 b,那就创建 b,结果创建 b 的时候又需要依赖 a ……
互相依赖何时了,死循环了吧? 诺,这就是循环依赖!
循环依赖其实不算个问题或者错误,我们实际在开发的时候,也可能会用到。 再拿最开始的 A 和 B 来说,我们手动使用的时候会用以下方式:
A a = new A();
B b = new B();
b.setA(a);
a.setB(b);
复制代码
其实这样就解决了循环依赖,功能上是没有问题的,但是为什么 Spring 要解决循环依赖?
为什么 Spring 要解决循环依赖?
首先简单了解下,我们用 Spring 框架,它帮我们做了什么事情?总结上来说,六字真言:IoC 和 AOP。
由于 Spring 解决循环依赖是考虑到 IoC 和 AOP 相关知识了,所以这里我先提一下。
由于本文主要的核心是 Spring 的循环依赖处理,所以不会对 IoC 和 AOP 做详细的说明,想了解以后有机会再说
IoC,主要是将对象的创建、管理都交给了 Spring 来管理,能够解决对象之间的耦合问题,对开发人员来说也是省时省力的。
AOP,主要是在不改变原有业务逻辑情况下,增强横切逻辑代码,也是解耦合,避免横切逻辑代码重复;也是对 OOP 的延续、补充。
既然类的实例化都交给了 Spring 来管理了,那么循环依赖 Spring 肯定也要考虑到怎么去处理(怎么总觉得有点像是废话 )。
解决循环依赖的方式
参考我们能想到的肯定是手动处理的方式,先将对象都 new 出来,然后进行 set 属性值,而 Spring 也是通过这样的形式来处理的(你说巧不巧?其实一点都不巧 ,后面再说为什么),其实 Spring 管理 Bean 的实例化底层其实是由反射实现的。
而我们实例化的方式也有好多种,比如通过构造函数,一次性将属性赋值,像下面这样
// 假设有这个类
public class Shop {
private int id;
private String name;
public Shop(int id, String name) {
this.id = id;
this.name = name;
}
}
// 通过构造器方式实例化并赋值
new Shop(1, "Suremotoo");
复制代码</