spring循环依赖的解决方案

spring循环依赖的解决方案

Spring IOC循环依赖解决方案分析

这里Spring主要用了三层缓存来完成对循环依赖的实现。

下面的属性来源于DefaultSingletonBeanRegistry类

    /** Cache of singleton objects: bean name --> bean instance */
    private final Map singletonObjects = new ConcurrentHashMap(64);

    /** Cache of singleton factories: bean name --> ObjectFactory */
    private final Map> singletonFactories = new HashMap>(16);

    /** Cache of early singleton objects: bean name --> bean instance */
    private final Map earlySingletonObjects = new HashMap(16);

当获取一个实例对象的时候,会调用此方法

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }

先从singletonObjects 找,如果找不到会从earlySingletonObjects中查询,再找不到去singletonFactories 中去查询,如果找到的话会放在earlySingletonObjects中,那么问题来了,singletonFactories的对象是什么时候放进去的。

研究Spring构造类实例的时候,通过AbstractAutowireCapableBeanFactory的doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)方法中调用addSingletonFactory方法将A类曝光到singletonFactories中。

    protected void addSingletonFactory(String beanName, ObjectFactory singletonFactory) {
        Assert.notNull(singletonFactory, "Singleton factory must not be null");
        synchronized (this.singletonObjects) {
            if (!this.singletonObjects.containsKey(beanName)) {
                this.singletonFactories.put(beanName, singletonFactory);
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.add(beanName);
            }
        }
    }

Spring注入一个类的大体步骤分为两部分,一是先完成对类的构造工作,二是会对类的属性进行设置和填充
那么关于的单例的类实例之间的互相引用的问题就清晰了

假设A对象有个属性B 则在A初始化的时候,构造完成之后就放在了singletonFactories中,当发现去set属性的时候发现B没有初始化,于是接着初始化B,设置属性的时候在缓存中都可以拿到各自对象的引用,所以不会有循环依赖的报错

你可能感兴趣的:(spring循环依赖的解决方案)