在spring框架下,咱们能够通过@Autowired注解对属性或者办法参数进行标注,当spring ioc容器初始化时,会帮咱们从容器中拿到对应的实例进行注入

什么是循环依赖

如果当初有两个Bean如下所示

public class BeanA {    @Autowired    private BeanB beanB;}public class BeanB {    @AutowiredgetSingleton    private BeanA beanA;}

而后咱们通过annotationConfigApplicationContext#register将两个bean的信息注入到容器中,最初通过refresh进行容器到初始化操作

public static void main(String[] args) {

    AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();    annotationConfigApplicationContext.register(Bean1.class);    annotationConfigApplicationContext.register(Bean2.class);    annotationConfigApplicationContext.refresh();}

能够看到A跟B相互依赖,试着设想:当容器先初始化beanA时,必然要对属性beanB进行赋值,这个时候容器中还没有beanB,那么势必会触发beanB的初始化流程,而beanB初始化的实现也须要对属性beanA赋值,但beanA还未初始化实现,这里就产生了所谓的循环依赖。

spring如何解决循环依赖

这里有一个很要害的属性:

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {    /** Cache of singleton factories: bean name to ObjectFactory. */    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);}

key是beanName,value是一个对象工厂,咱们点进去看一下

public interface ObjectFactory<T> {    T getObject() throws BeansException;}

其实这里的getObject()就是最终解决循环依赖所调用的办法。
那么程序是怎么执行到这的呢?
咱们先从bean的创立动手
如果容器还未实例化bean,那么就会走到这里

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)            throws BeanCreationException {        BeanWrapper instanceWrapper = null;        if (instanceWrapper == null) {            //实例化bean,如果@Autowired加在构造方法上,            //那么就会在这里实现注入            //因为上面的回调还未注册,所以这里无奈解决循环依赖            instanceWrapper = createBeanInstance(beanName, mbd, args);        }                final Object bean = instanceWrapper.getWrappedInstance();                boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&                isSingletonCurrentlyInCreation(beanName));        if (earlySingletonExposure) {            if (logger.isTraceEnabled()) {                logger.trace("Eagerly caching bean '" + beanName +                        "' to allow for resolving potential circular references");            }            //往单例工厂(之前说的singletonFactories)中增加一个            //ObjectFactory的匿名实现作为回调,            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));                        //属性赋值,解决@Autowired(非构造方法)            populateBean(beanName, mbd, instanceWrapper);        }

这里咱们发现,在实例化bean跟对属性赋值之间有一个addSingletonFactory的操作,作用是注册一个能够获取以后正在创立的bean的一个回调

    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {        synchronized (this.singletonObjects) {            if (!this.singletonObjects.containsKey(beanName)) {                this.singletonFactories.put(beanName, singletonFactory);            }        }    }

进入回调,发现回调默认返回的就是bean自身

    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {        Object exposedObject = bean;        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {            for (BeanPostProcessor bp : getBeanPostProcessors()) {                if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;                    exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);                }            }        }        return exposedObject;    }        default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {        //    返回bean自身        return bean;    }

ok,这里得出一个论断,即便bean未初始化实现,spring也提供了办法来获取这个bean的实例。
如果利用到咱们下面的栗子中来就是:

beanA实例化实现
增加获取beanA的回调到singletonFactories
调用populateBean,解决@Autowired,注入beanB
因为beanB还未创立,那么势必会进入创立beanB的流程,当beanB也走到populateBean时,也须要实现beanA的注入,这时就会尝试从beanFactory中获取beanA,这里最终会进到
AbstractBeanFactory的doGetBean中

    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);    }

这里很要害,进入getSingleton(beanName)

    public Object getSingleton(String beanName) {        return getSingleton(beanName, true);    }        protected Object getSingleton(String beanName, boolean allowEarlyReference) {        //先从一级缓存中查找        Object singletonObject = this.singletonObjects.get(beanName);        //如果一级缓存中没有,且以后bean正处于创立的过程中        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {            synchronized (this.singletonObjects) {                 //从二级缓存中查找                singletonObject = this.earlySingletonObjects.get(beanName);                 //如果二级缓存中也没有,且容许裸露晚期援用时                if (singletonObject == null && allowEarlyReference) {                    //从三级缓存中查找到bean的工厂                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);                    if (singletonFactory != null) {                        //调用getObject办法生成bean                        singletonObject = singletonFactory.getObject();                        //放入到二级缓存中                        this.earlySingletonObjects.put(beanName, singletonObject);                        //从三级缓存中移除                        this.singletonFactories.remove(beanName);                    }                }            }        }        return singletonObject;    }

当beanB走到这里时通过beanA的beanName获取beanA,首先会尝试从singletonObjects中获取,这里必定获取不到,因为singletonObjects的put操作是在bean初始化实现之后。所以只能通过调用之前注册的回调singletonFactory.getObject()来获取beanA。
那么到此beanA注入到beanB的顺利完成,当beanB初始化实现之后,其实beanA的getBean()也就返回了beanB的援用,到此beanA也能够顺利完成依赖注入。