Loading

三级缓存解析过程

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,如图所示
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对象。内存如图

对象B属性a赋值,通过三级缓存获取对象a之后

4 对象B属性a赋值完成

此时对象B的A属性为半成品的A对象。如图:
对象B属性a赋值完成

5 对象B加入一级缓存之前

与第4步相比,一二三级缓存未做任何修改。
对象B加入一级缓存之前

6 对象B加入一级缓存之后

对象B加入一级缓存,同时移除三级缓存中key值为b的键值对。
对象B加入一级缓存之后

7 对象A属性b获取到完整的B对象

此时B对象已完成初始化,存入一级缓存,获取到完整的B对象,此时B对象a属性已设置为半成品的A对象。内存如图:
对象A属性b获取到完整的B对象

8 A对象属性b赋值完成

A对象属性b赋值完成,此时A对象仍存储在二级缓存中。
A对象属性b赋值完成

9 A对象加入一级缓存之前

与第8步相比,内存未做变化。
A对象加入一级缓存之前

10 A对象加入一级缓存之后

此时A对象也写入一级缓存中,移除二级缓存中的A对象。AB对象都一初始化完成。
A对象加入一级缓存之后

posted @ 2024-03-25 08:45  zgcy123456  阅读(6)  评论(0编辑  收藏  举报