跳转至

手写 Spring 循环依赖

一、场景

A 依赖 B,B 依赖 A。

二、手写一个简化版

public class MyContainer {
    Map<String, Object> singletonObjects = new HashMap<>();
    Map<String, Object> earlyObjects = new HashMap<>();

    public Object getBean(String name) {
        // 1. 完整 Bean
        if (singletonObjects.containsKey(name))
            return singletonObjects.get(name);

        // 2. 早期 Bean(半成品)
        if (earlyObjects.containsKey(name))
            return earlyObjects.get(name);

        // 3. 实例化
        Object bean = createInstance(name);
        earlyObjects.put(name, bean);

        // 4. 属性填充
        populateBean(bean);

        // 5. 完成
        singletonObjects.put(name, bean);
        earlyObjects.remove(name);
        return bean;
    }
}

三、执行流程

创建 A

  1. getBean("A")。
  2. 实例化 A,放 earlyObjects。
  3. populateBean(A),发现需要 B。
  4. getBean("B")。

创建 B

  1. getBean("B")。
  2. 实例化 B,放 earlyObjects。
  3. populateBean(B),发现需要 A。
  4. getBean("A")。
  5. earlyObjects 有 A,返回半成品 A。
  6. B 拿到 A,属性填充完成。
  7. singletonObjects 放 B。

回到 A

  1. A 拿到 B,属性填充完成。
  2. singletonObjects 放 A。

四、这就是二级缓存

earlyObjects 就是二级缓存。

五、为什么 Spring 要三级

如果 A 被 AOP 代理,B 应该拿到代理对象,不是原始 A。三级缓存的 ObjectFactory 决定"要不要提前生成代理"。

一句话

手写循环依赖 = 实例化后先放 Map,填充时从 Map 拿。