目录
- Spring循环依赖流程图
- 场景:**A 依赖B**; **B依赖A、C**; **C依赖A**
- A,B, C三个类的定义
- 容器类
- 测试输入如下
- 总结
Spring循环依赖流程图
很早之前阅读源码写过总结:
https://github.com/doctording/spring-framework-5.1.3.RELEASE/blob/dev/docs/doc/bean/dependency.md
A,B相互依赖的创建流程即如下图所示:
场景:A 依赖B; B依赖A、C; C依赖A
A --> B
B --> A, C
C --> A
A,B, C三个类的定义
A
package com4;
public class A {
private B b;
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
}
B
package com4;
public class B {
private A a;
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
private C c;
public C getC() {
return c;
}
public void setC(C c) {
this.c = c;
}
}
C
package com4;
public class C {
private A a;
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
}
容器类
仿照spring框架源码编写如下java代码
package com4;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class Container {
Map<String, Class> beanMap = new HashMap<>(16);
public void addBean(String name, Class clazz){
beanMap.put(name, clazz);
}
Map<String, Object> singletonObjects = new HashMap<>(16);
Map<String, Object> earlySingletonObjects = new HashMap<>(16);
Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
private void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
}
}
private Object getSingleton(String beanName) throws Exception{
// 一级别缓存找
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
synchronized (this.singletonObjects) {
// 二级别缓存找
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 三级别缓存找
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// lambda执行后 塞到二级缓存中,并清空三级缓存
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
System.out.println("from singletonFactory to earlySingletonObjects bean:" + beanName);
}
} else { // 多加一个else 理解 earlySingletonObjects 和 singletonFactories
System.out.println("just get from earlySingletonObjects:" + beanName);
}
}
}
return singletonObject;
}
private Object getEarlyBeanReference(String name, Object o){
// 执行lambda,应用后处理 // TODO
System.out.println("execute lambda to get:" + name);
return o;
}
// 真正创建bean
public Object doCreateBean(String name) throws Exception{
System.out.println("crate bean: " + name);
if (this.singletonObjects.containsKey(name)) {
return this.singletonObjects.get(name);
}
// 初始化实例
Class clazz = beanMap.get(name);
Constructor constructor = clazz.getConstructors()[0];
constructor.setAccessible(true);
Object o = constructor.newInstance();
// 加入三级缓存中
System.out.println("add to singletonFactories bean:" + name);
singletonFactories.put(name, () -> getEarlyBeanReference(name, o));
Object exposedObj = o;
// 设置属性, 有循环依赖,假设field的set方法都是依赖哈
Field[] fields = exposedObj.getClass().getDeclaredFields();
for (Field field : fields) {
String name2 = field.getName();
String beanName2 = name2.toUpperCase();
Class clazz2 = field.getType();
System.out.println("resolve dependency bean: " + beanName2);
Object o2 = getSingleton(beanName2);
if (o2 == null) {
o2 = doCreateBean(beanName2);
}
String beanSetMethodName = "set" + beanName2;
Method method = clazz.getDeclaredMethod(beanSetMethodName, clazz2);
method.invoke(exposedObj, o2);
System.out.println(String.format("bean:%s set dependency bean:%s success", name, name2));
}
// 加入以及缓存并清空二级,三级缓存
System.out.println("addSingleton bean: " + name);
addSingleton(name, exposedObj);
return exposedObj;
}
public static void main(String[] args) throws Exception {
Container container = new Container();
container.addBean("A", A.class);
container.addBean("B", B.class);
container.addBean("C", C.class);
A a = (A) container.doCreateBean("A");
B b = (B) container.doCreateBean("B");
C c = (C) container.doCreateBean("C");
System.out.println("------------------------------");
System.out.println(a + ": " + a.getB());
System.out.println(b + ": " + b.getA() + ": " + b.getC());
System.out.println(c + ": " + c.getA());
}
测试输入如下
crate bean: A // 创建A
add to singletonFactories bean:A // 加入到三级缓存
resolve dependency bean: B
crate bean: B // 发现依赖B, 创建B
add to singletonFactories bean:B
resolve dependency bean: A // B依赖A
execute lambda to get:A // 三级缓存有A,执行并塞到二级缓存
from singletonFactory to earlySingletonObjects bean:A
bean:B set dependency bean:a success
resolve dependency bean: C
crate bean: C // B 依赖 C, 创建C
add to singletonFactories bean:C
resolve dependency bean: A
just get from earlySingletonObjects:A // C 依赖 A, 直接从二级缓存取
bean:C set dependency bean:a success
addSingleton bean: C // C创建完成
bean:B set dependency bean:c success
addSingleton bean: B // B创建完成
bean:A set dependency bean:b success
addSingleton bean: A // A创建完成
crate bean: B // 获取B从一级缓存直接取
crate bean: C // 获取C从一级缓存直接取
------------------------------
com4.A@3d075dc0: com4.B@214c265e
com4.B@214c265e: com4.A@3d075dc0: com4.C@448139f0
com4.C@448139f0: com4.A@3d075dc0
可以看到A,B,C 都成功创建, 且依赖关系也正确
总结
关于理解为什么需要三级缓存以及三级缓存的作用,通过本文实际例子是可以充分说明的。
实际上看:只有A,B的相互依赖,二级缓存就够了;只需要存储一个中间对象:A 创建依赖B, B创建依赖A,从这个中间缓存取就能完成创建B, 那么A也创建完成了,这样之后A,B都加入到一级缓存singletonObjects中,很完美。
但是考虑到上述A,B, C就可以多一个缓存了,考虑输出的注释
just get from earlySingletonObjects:A // C 依赖 A, 直接从二级缓存取
B、C都依赖A, B从中间缓存得到lambda且执行后可以再次进行缓存,这样C直接从这个缓存取出来用;依此类推,如果D、E、F…都依赖A,也是直接取出来,这样省了lambda的执行,所以二级缓存减少了这个开销,而三级缓存lambda则是必备,用来延迟加载获取依赖bean,拥有此缓存才能完成相互依赖的设置。
lambda延迟加载可以简单阅读我的博文:Java Function & Supplier 的实际例子对比感受抽象和懒加载
最后请读者仔细阅读代码直接拷贝然后去运行、多看看、已加深理解。如果有不一样的想法欢迎评论此博文进行交流。