手写Spring循环依赖-spring源码详解(四)

本文深入探讨了Spring框架中Bean的创建过程,特别是如何通过多级缓存机制解决循环依赖问题,并介绍了使用BeanPostProcessor实现动态代理的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上篇文章说了,bean工厂后置处理器如何加载配置类

BeanFactoryPostProcessor-spring源码详解(三)https://blog.youkuaiyun.com/ke1ying/article/details/127543302?spm=1001.2014.3001.5501

 public static void loadBeanDefinitions() {
        RootBeanDefinition rootBeanDefinitionA = new RootBeanDefinition(InstanceA.class);
        RootBeanDefinition rootBeanDefinitionB = new RootBeanDefinition(InstanceB.class);
        beanDefinitionMap.put("instanceA", rootBeanDefinitionA);
        beanDefinitionMap.put("instanceB", rootBeanDefinitionB);
    }

@Component
public class InstanceA {
    @Autowired
    private InstanceB instanceB;

    public InstanceB getInstanceB() {
        return instanceB;
    }

    public void setInstanceB(InstanceB instanceB) {
        this.instanceB = instanceB;
    }

    public InstanceA(InstanceB instanceB) {
        this.instanceB = instanceB;
    }

    public InstanceA() {
        System.out.println("实例化A");
    }
}

首先把bean放入beanDefinition,之后,循环bean定义,通过bean的key来获取beanDefinition,

通过无参构造函数反射来获取class,再赋值属性。

 public static void main(String[] args) throws Exception {
        // 加载到beanDefinition
        loadBeanDefinitions();

        for (String key : beanDefinitionMap.keySet()) {
            // 先创建A
            getBean(key);
        }
        InstanceA instanceA = (InstanceA)getBean("instanceA");
        System.out.println(instanceA);
    }

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

    public static Object getBean(String beanName) throws Exception {
        Object singleton = getSingleton(beanName);
        if(singleton != null){
            return singleton;
        }

        // 实例化
        RootBeanDefinition rootBeanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
        Class<?> beanClass = rootBeanDefinition.getBeanClass();
        // 通过class 无参构造函数 实例化
        Object instanceBean = beanClass.newInstance();

        singletonObjects.put(beanName, instanceBean);
        // 属性赋值
        Field[] declaredFields = beanClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            Autowired annotation = declaredField.getAnnotation(Autowired.class);
            // 说明bean有autowired
            if (annotation != null) {
                // 打开访问权限
                declaredField.setAccessible(true);
                // byName  byType   拿到了 instanceB名字
                String name = declaredField.getName();
                // 拿到B的bean
                Object fileObject = getBean(name);
                declaredField.set(instanceBean, fileObject);
            }
        }
        // 初始化
        // 放入缓存
//        singletonObjects.put(beanName, instanceBean);
        return instanceBean;
    }

    private static Object getSingleton(String beanName) {
        Object singleton = singletonObjects.get(beanName);
        if (singleton != null) {
            return singleton;
        }
        return null;
    }

这样写完之后,就不会有死循环,但是没有用到二级缓存,二级缓存可以用来放半成品的bean,解决多线程的情况下,多个线程同时创建bean,防止其他线程拿到不完整的bean,于是 加上二级缓存来写。

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

    public static Object getBean(String beanName) throws Exception {
        Object singleton = getSingleton(beanName);
        if (singleton != null) {
            return singleton;
        }

        // 实例化
        RootBeanDefinition rootBeanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
        Class<?> beanClass = rootBeanDefinition.getBeanClass();
        // 通过class 无参构造函数 实例化
        Object instanceBean = beanClass.newInstance();

        // 二级缓存
        earlySingletonObjects.put(beanName, instanceBean);
        // 属性赋值
        Field[] declaredFields = beanClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            Autowired annotation = declaredField.getAnnotation(Autowired.class);
            // 说明bean有autowired
            if (annotation != null) {
                // 打开访问权限
                declaredField.setAccessible(true);
                // byName  byType   拿到了 instanceB名字
                String name = declaredField.getName();
                // 拿到B的bean
                Object fileObject = getBean(name);
                declaredField.set(instanceBean, fileObject);
            }
        }
        // 初始化
        // 放入缓存
        singletonObjects.put(beanName, instanceBean);
        return instanceBean;
    }

    private static Object getSingleton(String beanName) {
        Object singleton = singletonObjects.get(beanName);
        if (singleton != null) {
            return singleton;
        }
        Object earlySingleton = earlySingletonObjects.get(beanName);
        if (earlySingleton != null) {
            return earlySingleton;
        }
        return null;
    }

用解耦的方式,beanPostProcessor来创建动态代理。

如果在最后调用动态代理,这时候循环依赖的bean就不是动态代理的bean,所以要在之前就创建动态代理。所以这里有两个地方调用动态代理,实例化之后和初始化之后调用。

只在循环依赖的情况下在实例化之后创建动态代理,所以需要判断当前是不是循环依赖。

前面一级缓存中没拿到,而二级缓存中有,才是循环依赖。

而spring源码里有一行代码,用来判断是否是循环依赖,加了一个正在创建对象的标识。

  private static Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
    private static Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();
    // 存放函数接口
    private static Map<String, ObjectFactory> singletonFactories = new ConcurrentHashMap<>();

    private static Set<String> singletonCurrennlyInCreation = new HashSet<>();

    public static Object getBean(String beanName) throws Exception {
        Object singleton = getSingleton(beanName);
        if (singleton != null) {
            return singleton;
        }

        // 正在创建
        if (!singletonCurrennlyInCreation.contains(beanName)) {
            singletonCurrennlyInCreation.add(beanName);
        }

        // 实例化
        RootBeanDefinition rootBeanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
        Class<?> beanClass = rootBeanDefinition.getBeanClass();
        // 通过class 无参构造函数 实例化
        Object instanceBean = beanClass.newInstance();

        // 创建动态代理
        // 只在循环依赖的情况下在实例化之后创建动态代理
        //Object o = new JDKProxyBeanPostProcessor().getEarlyBeanReference(instanceBean,beanName);
        /*singletonFactories.put(beanName, new ObjectFactory() {
            @Override
            public Object getObject() throws BeansException {
                return  new JDKProxyBeanPostProcessor().getEarlyBeanReference(instanceBean,beanName);
            }
        });*/
        singletonFactories.put(beanName, () -> new JDKProxyBeanPostProcessor().getEarlyBeanReference(instanceBean, beanName));

        // 二级缓存
        //earlySingletonObjects.put(beanName, instanceBean);
        // 属性赋值
        Field[] declaredFields = beanClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            Autowired annotation = declaredField.getAnnotation(Autowired.class);
            // 说明bean有autowired
            if (annotation != null) {
                // 打开访问权限
                declaredField.setAccessible(true);
                // byName  byType   拿到了 instanceB名字
                String name = declaredField.getName();
                // 拿到B的bean
                Object fileObject = getBean(name);
                declaredField.set(instanceBean, fileObject);
            }
        }
        // 初始化


        /*if(earlySingletonObjects.containsKey(beanName)){
            instanceBean = earlySingletonObjects.get(beanName);
        }*/
        // 放入缓存
        singletonObjects.put(beanName, instanceBean);
        return instanceBean;
    }

    private static Object getSingleton(String beanName) {
      /*  Object singleton = singletonObjects.get(beanName);
        if (singleton != null) {
            return singleton;
        }
        Object earlySingleton = earlySingletonObjects.get(beanName);
        if (earlySingleton != null) {

            return earlySingleton;
        }
        return null;*/
        Object bean = singletonObjects.get(beanName);
        if (bean == null && singletonCurrennlyInCreation.contains(beanName)) {
            // 是循环依赖
            bean  = earlySingletonObjects.get(beanName);
            synchronized (singletonObjects){
                if(bean == null){
                    ObjectFactory objectFactory = singletonFactories.get(beanName);
                    if (objectFactory != null) {
                        // 钩子函数 去创建 aop代理
                        bean = objectFactory.getObject();
                        earlySingletonObjects.put(beanName, bean);
                        singletonFactories.remove(beanName);
                    }
                    return bean;
                }
            }
        }
        return bean;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后端从入门到精通

你的鼓励是我最大的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值