白话理解什么是Spring循环依赖
我们知道Spring IOC是指的容器来负责创建Bean并负责处理Bean之间的依赖关系,比如有如下两个类A、B:
@Component
public class A
@Autowired
private B b;
@Component
public class B
站在容器的角度,发现A依赖B,直接先创建B然后创建A,把B实例赋值给A的成员变量b,完事儿。
但如果是下面一种循环依赖的情况,按照上面的逻辑就不行了:
循环依赖
@Component
public class A
@Autowired
private B b;
@Component
public class B
@Autowired
private C c;
@Component
public class C
@Autowired
private A a;
A依赖B、B依赖C、C又依赖A
如果你是容器,尼玛到底该先创建谁??
解决思路
创建一个类实例之前,先去一个全局的缓存Map里看下是否有这个类的实例,如果有则说明已经创建过、直接返回,如果没有则创建。
创建类实例的对应的属性的实例、并赋值给成员变量。递归。
创建A的实例,加入缓存Map,遍历A的属性,发现B需要创建,创建B的实例也加入缓存,遍历B的属性发现需要创建C,创建C的实例,遍历C的属性发现需要创建A的实例,但是A实例已经在缓存了、直接赋值。循环结束。
下面按照上面的思路,写下代码模拟循环依赖的解决:
package com.wangan.cyclicdependency;
public class A {
public B b;
}
public class B {
public C c;
}
public class C {
public A a;
}
package com.wangan.cyclicdependency;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* 模拟简单循环依赖解决
* */
public class TestCyclicDependency {
private static Map beanCache = new HashMap<>();
public static void main(String[] args) throws Exception {
String[] beanDefinations = {"com.wangan.cyclicdependency.A",
"com.wangan.cyclicdependency.B",
"com.wangan.cyclicdependency.C"};
for(String beanName : beanDefinations) {
getBean(beanName);
}
A a = (A) beanCache.get("com.wangan.cyclicdependency.A");
B b = (B) beanCache.get("com.wangan.cyclicdependency.B");
C c = (C) beanCache.get("com.wangan.cyclicdependency.C");
System.out.println(a.b);
System.out.println(b.c);
System.out.println(c.a);
System.out.println(a.b==b);
System.out.println(b.c==c);
System.out.println(c.a==a);
}
public static Object getBean(String beanName) throws Exception {
if(beanCache.containsKey(beanName)) {
return beanCache.get(beanName);
}else {
Object bean = Class.forName(beanName).newInstance();
beanCache.put(beanName, bean);
Field[] fields = bean.getClass().getFields();
for(Field f : fields) {
String typeClassName = f.getType().getName();
f.setAccessible(true);
f.set(bean, getBean(typeClassName));
}
return bean;
}
}
}