三级缓存用于解决Spring循环依赖的问题,循环依赖呈现于bean的初始化环节,对于bean初始化能够参考Bean源码解析,以下从源码的角度剖析三级缓存的作用机理。

1.源码位于org.springframework.beans.factory.support下的DefaultSingletonBeanRegistry

// 一级缓存,寄存齐全初始化的bean/** Cache of singleton objects: bean name to bean instance. */private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);// 二级缓存,寄存半成品bean/** Cache of early singleton objects: bean name to bean instance. */private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);// 三级缓存,寄存实例化的bean/** Cache of singleton factories: bean name to ObjectFactory. */private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

假如一个场景,A依赖B,B依赖A。

2.创立A对象,从org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean开始

    /**     * Return an instance, which may be shared or independent, of the specified bean.     * @param name the name of the bean to retrieve     * @param requiredType the required type of the bean to retrieve     * @param args arguments to use when creating a bean instance using explicit arguments     * (only applied when creating a new instance as opposed to retrieving an existing one)     * @param typeCheckOnly whether the instance is obtained for a type check,     * not for actual use     * @return an instance of the bean     * @throws BeansException if the bean could not be created     */    @SuppressWarnings("unchecked")    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {        final String beanName = transformedBeanName(name);        Object bean;        // Eagerly check singleton cache for manually registered singletons.        Object sharedInstance = getSingleton(beanName);        if (sharedInstance != null && args == null) {            if (logger.isTraceEnabled()) {                if (isSingletonCurrentlyInCreation(beanName)) {                    logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +                            "' that is not fully initialized yet - a consequence of a circular reference");                }                else {                    logger.trace("Returning cached instance of singleton bean '" + beanName + "'");                }            }            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);        }

其中,首先会查看缓存中是否有对象Object sharedInstance = getSingleton(beanName);,如果有,就从缓存中取,bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);

3.而后看看org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton办法

    /**     * Return the (raw) singleton object registered under the given name.     * <p>Checks already instantiated singletons and also allows for an early     * reference to a currently created singleton (resolving a circular reference).     * @param beanName the name of the bean to look for     * @param allowEarlyReference whether early references should be created or not     * @return the registered singleton object, or {@code null} if none found     */    @Nullable    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;    }

代码很简略,顺次查问三级缓存,如果缓存中存在就间接返回,特地地,在第三级,如果取得了bean,就在第三级移除bean,在第二级增加。

所以到这里应该就完结了。

问题:二级缓存可不可以?

这个其实是设计的问题,设计之初认为AOP代理是在实例化实现后的行为,所以三级是为了解决AOP,二级是为了效率,如果有多个循环依赖,间接从二级获取到加强的对象,不用二次加强。