三级缓存解析过程
Hello World
在spring中,对象的创建可以分为实例化和初始化,实例化完成但未完成初始化的对象时可以直接给其他对象引用的,所以此时可以做一件事,把实例化完成,但初始化未完成的对象提前暴露出去,让其他对象能够进行引用,即提前暴露对象。
三级缓存代码示例如下
package com.gientech.cycle;
public class A {
private B b;
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
public A (){
System.out.println("this is A ");
}
@Override
public String toString() {
return "A{" +
"b=" + b +
'}';
}
}
package com.gientech.cycle;
public class B {
private A a;
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
public B(){
System.out.println("this is b ");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="a" class="com.gientech.cycle.A">
<property name="b" ref="b"></property>
</bean>
<bean id="b" class="com.gientech.cycle.B">
<property name="a" ref="a"></property>
</bean>
</beans>
package com.gientech.cycle;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestCycle {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("cycle.xml");
A bean = ac.getBean(A.class);
System.out.println(bean.getB());
System.out.println("test ================ ");
B bean1 = ac.getBean(B.class);
System.out.println(bean1.getA());
}
}
运行结果如下
三级缓存处理步骤如下
1 对象A实例化完成
对象A实例化完成,但未完成初始化,A对象的属性b为null,此时A存放在registeredSingletons集合中,三级缓存中存放key为a, value为lambda表达式的键值对。一二三级缓存中均未存放A,如图所示
2 对象B实例化完成
接下来需要给A对象的属性b赋值,容器中没有B对象,会新建B对象,B对象实例化完成后,B对象的属性a为null, B对象也是存放在registeredSingletons集合中,三级缓存中新增加一个键值对,key为b, value为lambda表达式,此时三级缓存中有key为a,b 的两个键值对,且value均为lambda表达式。一二三级缓存中均未存放A,B对象,内存截图如下
3 对象B属性a赋值,通过三级缓存获取对象a之后
B对象实例化完成后,需要给a属性赋值,此时a对象存储在registeredSingletons集合中,获取到半成品的a对象之后,移除三级缓存中key值为a的键值对,在二级缓存中存入key为a的键值对,value 为半成品的a对象。内存如图
4 对象B属性a赋值完成
此时对象B的A属性为半成品的A对象。如图:
5 对象B加入一级缓存之前
与第4步相比,一二三级缓存未做任何修改。
6 对象B加入一级缓存之后
对象B加入一级缓存,同时移除三级缓存中key值为b的键值对。
7 对象A属性b获取到完整的B对象
此时B对象已完成初始化,存入一级缓存,获取到完整的B对象,此时B对象a属性已设置为半成品的A对象。内存如图:
8 A对象属性b赋值完成
A对象属性b赋值完成,此时A对象仍存储在二级缓存中。
9 A对象加入一级缓存之前
与第8步相比,内存未做变化。
10 A对象加入一级缓存之后
此时A对象也写入一级缓存中,移除二级缓存中的A对象。AB对象都一初始化完成。