第15章:通过三级缓存解决循环依赖

前面章节 请参看tiny-spring或者小傅哥的small-spring

代码变更对比图

在这里插入图片描述

解析

实例1:类似死锁,一个类A实例化对象的时候,A对象的属性包含一个类B的对象;



public class CircleTest {

    private final static Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    public static void main(String[] args) throws Exception {
        System.out.println(getBean(B.class).getA());
        System.out.println(getBean(A.class).getB());
    }

    private static <T> T getBean(Class<T> beanClass) throws Exception {
        String beanName = beanClass.getSimpleName().toLowerCase();
        if (singletonObjects.containsKey(beanName)) {
            return (T) singletonObjects.get(beanName);
        }
        // 实例化对象入缓存
        Object obj = beanClass.newInstance();
        singletonObjects.put(beanName, obj);
        // 属性填充补全对象
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            Class<?> fieldClass = field.getType();
            String fieldBeanName = fieldClass.getSimpleName().toLowerCase();
            field.set(obj, singletonObjects.containsKey(fieldBeanName) ? singletonObjects.get(fieldBeanName) : getBean(fieldClass));
            field.setAccessible(false);
        }
        return (T) obj;
    }

}

class A {

    private B b;

    public B getB() {
        return b;
    }

    public void setB(B b) {
        this.b = b;
    }
}

class B {

    private A a;

    public A getA() {
        return a;
    }

    public void setA(A a) {
        this.a = a;
    }
}


通过缓存我们先把实例化好的但是没有赋值属性的对象放入缓存,
然后再设置属性的时候通过缓存这个“中间人”来达到处理循环依赖的问题。

构造器注入Spring也不能解决

源码分析


/**
 *
 */
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {

    /**
     * Internal marker for a null singleton object:
     * used as marker value for concurrent Maps (which don't support null values).
     */
    protected static final Object NULL_OBJECT = new Object();

    /**
     * 一级缓存,普通对象
     * Cache of sinleton Objects:bean Name --> bean Instance
     */
    private Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
    /**
     * 二级缓存, 提前暴露对象,没有完全实例化的对象
     * Cache of early sinleton objects: bean name --> bean instance
     */
    private final Map<String, Object> earlySinletonObjects = new HashMap<>();
    /**
     * 三级缓存, 存放的代理对象
     * Cache of sinleton fatories: bean name --> ObjectFactory
     */
    private final Map<String, ObjectFatory<?>> sinletonFactories = new HashMap<>();

    private final Map<String, DisposableBean> disposableBeans = new LinkedHashMap<>();

    /**
     * 获取单例对象:
     * 1、从一级缓存拿
     * 2、一级缓存卫康:去二级缓存拿
     * 3、二级缓存为空:去三级缓存拿
     * 4、三级缓存如有:拿出来并放入二级缓存,并在三级缓存remove这个单例
     * 5、返回实例
     */
    @Override
    public Object getSingleton(String beanName) {
        Object singletonObject = singletonObjects.get(beanName);
        if (singletonObject == null) {
            singletonObject = earlySinletonObjects.get(beanName);
            if (singletonObject == null) {
                ObjectFatory<?> sinletonFactory = sinletonFactories.get(beanName);
                if (sinletonFactory != null) {
                    singletonObject = sinletonFactory.getObject();
                    earlySinletonObjects.put(beanName, singletonObject);
                    sinletonFactories.remove(beanName);
                }
            }
        }
        return singletonObject;
    }

    /**
     * 注册单例对象:
     * 1、放入一级缓存
     * 2、清空二级缓存
     * 3、清空三级缓存
     */
    public void registerSingleton(String beanName, Object singletonObject) {
        singletonObjects.put(beanName, singletonObject);
        earlySinletonObjects.remove(beanName);
        sinletonFactories.remove(beanName);
    }

    protected void addSingletonFactory(String beanName, ObjectFatory<?> sinletonFactory) {
        if (!this.singletonObjects.containsKey(beanName)) {
            this.sinletonFactories.put(beanName, sinletonFactory);
            this.earlySinletonObjects.remove(beanName);
        }
    }

    public void registerDisposableBean(String beanName, DisposableBean bean) {
        disposableBeans.put(beanName, bean);
    }

    public void destroySingletons() {
        Set<String> keySet = this.disposableBeans.keySet();
        Object[] disposableBeanNames = keySet.toArray();

        for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
            Object beanName = disposableBeanNames[i];
            DisposableBean disposableBean = disposableBeans.remove(beanName);
            try {
                disposableBean.destroy();
            } catch (Exception e) {
                throw new BeansException("Destroy method on bean with name '" + beanName + "' threw an exception", e);
            }
        }
    }

先注意看我们的默认单例bean注册器实现类DefaultSingletonBeanRegistry ,
他里面就通过三个map分别实现了三个缓存,也就是三级缓存:
singletonObjects、earlySinletonObjects、sinletonFactories
	- singletonObjects一级保存完整的单例bean;
	- earlySinletonObjects二级缓存未完全实例化赋值属性的bean;
	- sinletonFactories三级处理的就是AOP对象,为了避免重复生成新的AOP对象违背单例的设计。

网上流程解析图

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值