Spring解决循环依赖其实就用了个递归
本文用简要代码事例解释了Spring如何能解决依赖循环,并不讨论实际源码涉及的诸多因数,比如为什么有3个集合。
重点:
1、用3个集合来解决循环依赖,需要清楚3个集合分别是存什么
2、开始条件:使用
Supplier来延迟 Bean 的创建,确保只有在需要时才创建 Bean。看下代码中private Map<String, Supplier<?>> singletonFactories = new HashMap<>();
3、查找顺序,①先从singletonObjects 找,②找不到再从earlySingletonObjects找,③再找不到从singletonFactories创建并放到earlySingletonObjects中。假设这个方法叫getBean。
4、从singletonFactories创建的时候遇到依赖会调用getBean获取,这相当于递归过程。当遇到依赖循环的时候,递归会在调用步骤②的时候结束。相当于结束条件。
模拟代码:
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;class A {private B b;public void setB(B b) {this.b = b;}@Overridepublic String toString() {return "A{" +"b=" + (b != null ? "B" : "null") +'}';}
}class B {private A a;public void setA(A a) {this.a = a;}@Overridepublic String toString() {return "B{" +"a=" + (a != null ? "A" : "null") +'}';}
}public class CircularDependencyDemo {private Map<String, Object> singletonObjects = new HashMap<>();private Map<String, Object> earlySingletonObjects = new HashMap<>();private Map<String, Supplier<?>> singletonFactories = new HashMap<>();public static void main(String[] args) {CircularDependencyDemo demo = new CircularDependencyDemo();demo.resolveCircularDependency();}public void resolveCircularDependency() {//创建 A 的工厂并放入 singletonFactoriessingletonFactories.put("a", () -> {A a = new A();earlySingletonObjects.put("a", a);//初始化 A 时发现需要 Ba.setB(getBean("b"));return a;});//创建 B 的工厂并放入 singletonFactoriessingletonFactories.put("b", () -> {B b = new B();earlySingletonObjects.put("b", b);//初始化 B 时发现需要 Ab.setA(getBean("a"));return b;});//初始化 A 和 BA a = getBean("a");B b = getBean("b");//完成初始化后将 A 和 B 移动到 singletonObjectssingletonObjects.put("a", a);singletonObjects.put("b", b);System.out.println(singletonObjects.get("a"));System.out.println(singletonObjects.get("b"));}//查找顺序private <T> T getBean(String beanName) {if (singletonObjects.containsKey(beanName)) {return (T) singletonObjects.get(beanName);}if (earlySingletonObjects.containsKey(beanName)) {return (T) earlySingletonObjects.get(beanName);}if (singletonFactories.containsKey(beanName)) {Supplier<?> factory = singletonFactories.remove(beanName);T object = (T) factory.get();//这里隐藏着递归过程earlySingletonObjects.put(beanName, object);return object;}throw new RuntimeException("Bean not found: " + beanName);}
}
