Spring是如何解决循环依赖的

Easter79
• 阅读 501

​ 在某一次面试中,对方问了一个问题:Spring的Bean如果互相依赖,会发生什么?由于我那段时间正好遇到了一个Spring循环依赖报错的问题,就回答会报错。然后听对方口气,感觉自己答错了。于是事后了解了一下,才发现其实Spring自身解决了循环依赖的问题。


​ Spring的启动后,会读取配置文件,资源文件读取校验,创建BeanFactory,解析配置文件创建BeanDefinition,注册到BeanFactory,注册各种默认处理器,加载国际化、事件广播、监听器等,最后实例化非延迟初始化的单例。

代码关键点如下:

AbstractApplicationContext.refresh()    //加载配置,启动容器

​    AbstractApplicationContext.finishBeanFactoryInitialization()

​        DefaultListableBeanFactory.preInstantiateSingletons()    //实例化单例

​            AbstractBeanFactory.getBean()    //获取bean,触发创建

​            AbstractBeanFactory.doGetBean()

​                DefaultSingletonBeanRegistry.getSingleton()    //获取bean触发bean的创建并缓存

​                    AbstractAutowireCapableBeanFactory.createBean()    //InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()提前创建bean

​                    AbstractAutowireCapableBeanFactory.doCreateBean()    //创建bean

​                    AbstractAutowireCapableBeanFactory.populateBean()    //注入

​                    AbstractAutowireCapableBeanFactory.initializeBean()    //初始化,afterPropertiesSet、initMethod、Aware注入、postProcessAfterInitialization()

​ 以一个简单循环依赖为例,两个普通的互相依赖的Bean(非延迟初始化的单例)。

@Component
public class ServiceA {
    private ServiceB serviceB;
    public ServiceA() {
        System.out.println("ServiceA()");
    }
    public void foo() {
        System.out.println("serviceA.foo()");
        serviceB.foo();
    }
    @Autowired
    public void setServiceB(ServiceB serviceB) {
        System.out.println("serviceA.setServiceB()");
        this.serviceB = serviceB;
    }
}
@Component
public class ServiceB {
    private ServiceA serviceA;
    public ServiceB() {
        System.out.println("serviceB()");
    }
    public void foo() {
        System.out.println("serviceB.foo()");
    }
    @Autowired
    public void setServiceA(ServiceA serviceA) {
        System.out.println("serviceB.setServiceA()");
        this.serviceA = serviceA;
    }
}
@Configuration
@ComponentScan
public class SetMain {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainApplication.class);
        System.out.println("start");
        context.getBean(ServiceA.class).foo();
    }
}

执行后,会打印

ServiceA()
ServiceB()
serviceB.setServiceA()
serviceA.setServiceB()
start
serviceA.foo()
serviceB.foo()

可以发现,Spring启动先后创建了ServiceA、ServiceB实例,但是先调用了ServiceB的set方法注入ServiceA,然后调用ServiceA的set方法注入ServiceB,并未报错。可见Spring在启动的时候,就把循环依赖处理掉了。于是跟踪查看源码:

  1. Spring启动时会调用AbstractApplicationContext.refresh(),加载并解析配置文件,创建BeanDefinition,加载并执行各种PostProcessors等,最后初始化剩余的非延迟初始化的单例(……)

    public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. // 准备,设置其启动时间、活动标志、初始化属性源 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. // 解析配置,创建Beanfactory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. // 配置BeanFactory,例如默认ClassLoader和各种处理器 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. // 允许在上下文子类中对bean工厂进行后处理。 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. // 执行所有注册为bean的BeanFactoryPostProcessor invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. // 注册BeanPostProcessor bean registerBeanPostProcessors(beanFactory); // Initialize message source for this context. // 初始化MessageSource,用于国际化 initMessageSource(); // Initialize event multicaster for this context. // 初始化事件广播 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. // 初始化特定上下文子类中的其他特殊bean。 onRefresh(); // Check for listener beans and register them. // 检查监听器bean并注册它们 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. // 实例化所有剩余的(非延迟初始化)单例 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { ... } finally { ... } } } }

  2. 获取所有bean名字,当bean满足非抽象、单例、非延迟初始化条件时,调用getBean()触发bean初始化。

    public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { @Override public void preInstantiateSingletons() throws BeansException { ... List beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // 非抽象、单例、非延迟初始化 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { final FactoryBean factory = (FactoryBean) bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged((PrivilegedAction) ((SmartFactoryBean) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else { // 不是FactoryBean,普通bean getBean(beanName); } } } ... } }

  3. 尝试获取bean,如果取不到,就创建

    public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    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);
        } else {
            // 获取不到,bean没有被创建
    
            // Fail if we're already creating this bean instance: We're assumably within a circular reference.
            // 如果我们已经在创建这个bean实例,则失败: 我们假设在一个循环引用中。
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
    
            // Check if bean definition exists in this factory.
            // 从parent中获取bean
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                } else if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                } else if (requiredType != null) {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                } else {
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }
    
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }
    
            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);
    
                // Guarantee initialization of beans that the current bean depends on.
                // 处理@DependsOn
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        registerDependentBean(dep, beanName);
                        try {
                            getBean(dep);
                        } catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }
    
                // Create bean instance.
                // 创建bean实例
                if (mbd.isSingleton()) {
                    // 获取/创建
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        } catch (BeansException ex) {
                            ...
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
                ...
            } catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }
    }
    

    }

  4. 开始真正创建bean,首先实例化对象,然后执行注入,并执行各种初始化回调和初始化方法

    public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { if (instanceWrapper == null) { //创建实例 instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } ... // Eagerly cache singletons to be able to resolve circular references even when triggered by lifecycle interfaces like BeanFactoryAware. // 急切地缓存(敏感词?)单例,以便在像BeanFactoryAware这样的生命周期接口触发时也能够解析循环引用。 // 单例、允许循环依赖(AbstractAutowireCapableBeanFactory.setAllowCircularReferences())、单例正在创建中(DefaultSingletonBeanRegistry.getSingleton()时加入的) 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"); } //设置单例工厂 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { //填充bean,注入 populateBean(beanName, mbd, instanceWrapper); //初始化bean,执行各种回调、初始化方法等 exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { ... } return exposedObject; } protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { ... boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; //ImportAwareBeanPostProcessor、AutowiredAnnotationBeanPostProcessor PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } ... } }

  5. 注入是通过AutowiredAnnotationBeanPostProcessor完成的

    public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware { public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex); } return pvs; } }

  6. 以方法注入为例,根据方法获取参数类型,并从BeanFactory中获取,通过反射调用方法,完成注入

    public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware { private class AutowiredMethodElement extends InjectionMetadata.InjectedElement { ... @Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { ... Method method = (Method) this.member; Object[] arguments; if (this.cached) { // Shortcut for avoiding synchronization... arguments = resolveCachedArguments(beanName); } else { Class<?>[] paramTypes = method.getParameterTypes(); arguments = new Object[paramTypes.length]; DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length]; Set autowiredBeans = new LinkedHashSet<>(paramTypes.length); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); for (int i = 0; i < arguments.length; i++) { MethodParameter methodParam = new MethodParameter(method, i); DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required); currDesc.setContainingClass(bean.getClass()); descriptors[i] = currDesc; try { // 获取依赖 Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter); if (arg == null && !this.required) { arguments = null; break; } arguments[i] = arg; } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex); } } ... if (arguments != null) { try { // 反射注入 ReflectionUtils.makeAccessible(method); method.invoke(bean, arguments); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } } } }

  7. 对于普通bean,获取依赖最终会调用到AbstractBeanFactory.getBean()。此时开始创建ServiceB,过程跟ServiceA一致。当创建完ServiceB后,需要注入ServiceA时,会再次来到AbstractBeanFactory.getBean()。这次情况就不一样了,因为在创建ServiceA的时候,singletonsCurrentlyInCreation中保存了beanName。

    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { ... //beanName加入singletonsCurrentlyInCreation beforeSingletonCreation(beanName); ... try { singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { ... } finally { ... } if (newSingleton) { //创建bean完成 addSingleton(beanName, singletonObject); } } return singletonObject; } } // 首次创建ServiceA时,保存了beanName protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } } //把bean放入singletonObjects protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }

同时,在创建ServiceA时保存了ObjectFactory,并传入了刚刚创建的ServiceA对象。

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        //刚new的对象
        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,把bean传入
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, 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) {
                    //默认情况全部返回bean,不做修改
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                    exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                }
            }
        }
        return exposedObject;
    }
}
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(singletonFactory, "Singleton factory must not be null");
        synchronized (this.singletonObjects) {
            if (!this.singletonObjects.containsKey(beanName)) {
                // 第一次创建ServiceA时,保存ObjectFactory
                this.singletonFactories.put(beanName, singletonFactory);
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.add(beanName);
            }
        }
    }
}

当ServiceB尝试获取ServiceA时,就会从singletonFactories中获取ObjectFactory,调用工厂获取之前放入的ServiceA对象。所以这里会直接返回新创建且没有初始化的ServiceA(serviceB=null)对象,并注入到ServiceB中。ServiceB初始化完成之后,将返回ServiceB(serviceA=servieA(serviceB=null))对象注入到ServiceA中,此时ServiceB(serviceA=servieA(serviceB=serviceB))中的ServiceA对象也就包含了ServiceB的引用了。至此,循环依赖就完成了。

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    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) {
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
        ...
    }
}
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        //第一次,返回false,执行创,DefaultSingletonBeanRegistry.getSingleton(String,ObjectFactory)#beforeSingletonCreation保存了beanName
        //第二次,返回true
        //bena创建完成后从singletonObjects能直接获取
        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) {
                        // 调用工厂创建,AbstractAutowireCapableBeanFactory.doCreateBean()#addSingletonFactory()设置的
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }
    private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
    public boolean isSingletonCurrentlyInCreation(String beanName) {
        return this.singletonsCurrentlyInCreation.contains(beanName);
    }
}

这个功能的要点就在DefaultSingletonBeanRegistry.getSingleton()中,当创建ServiceA时,会把ObjectFactory放入singletonFactories中,当创建ServiceB需要注入ServiceA时,获得ObjectFactory,拿到ServiceA对象,并放入earlySingletonObjects中,这个过程中有其他bean依赖ServiceA就可以直接从earlySingletonObjects获取。当ServiceA初始化过程完成,把bean放入singletonObjects,当其他bean依赖ServiceA时,直接从singletonObjects中获取。


可见,Spring解决了循环依赖问题,那为什么我会遇到报错呢。因为我接手了IDE的建议,把注入方式改成了构造方法注入。

@Component
public class ServiceA {
    private final ServiceB serviceB;

    @Autowired
    public ServiceA(ServiceB serviceB) {
        System.out.println("ServiceA()");
        this.serviceB = serviceB;
    }

    public void foo() {
        System.out.println("serviceA.foo()");
        serviceB.foo();
    }
}
@Component
public class ServiceB {
    private final ServiceA serviceA;

    @Autowired
    public ServiceB(ServiceA serviceA) {
        System.out.println("ServiceB()");
        this.serviceA = serviceA;
    }

    public void foo() {
        System.out.println("serviceB.foo()");
    }
}
@Configuration
@ComponentScan
public class ConstructorMain {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConstructorMain.class);
        System.out.println("start");
        context.getBean(ServiceA.class).foo();
    }
}

执行后Spring启动报错,告知依赖的bean正在创建中,可能有循环引用

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'serviceA': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:374)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:250)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:273)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1247)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1177)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:857)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:760)
    ... 28 more

因为用构造方法注入后,在创建对象时必须传入依赖,如果两个bean互相引用,就必须对方先现实化,产生“死循环”,从逻辑上就有问题。而在Spring里对这种场景的处理,前面步骤基本一致:

  • 创建ServiceA实例,发现ServiceA是构造方法注入,根据构造方法参数类型,从BeanFactory查找ServiceB。

  • 创建ServiceB实例,发现ServiceB是构造方法注入,根据构造方法参数类型,从BeanFactory查找ServiceA。

  • 由于ServiceA目前还在实例化,并没有走到缓存那一步,所以获取不到ServiceA的实例化对象。于是触发创建bean,由于在创建ServiceA时保存了singletonsCurrentlyInCreation,所以此时检验发现ServiceA正在创建中,于是抛出异常。

    public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { protected T doGetBean(final String name, @Nullable final Class requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; // 由于ServiceA尚未初始化,所以这里取不到 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { ... } else { try { ... // 创建 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { ... } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); ... } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } ... return (T) bean; } }

    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { ... // ServiceA创建时beanName加入singletonsCurrentlyInCreation // 当ServiceB试图获取ServiceA时,检查 beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { ... } catch (BeanCreationException ex) { ... } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } //beanName从singletonsCurrentlyInCreation移除 afterSingletonCreation(beanName); } ... } return singletonObject; } } private final Set singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16)); protected void beforeSingletonCreation(String beanName) { // 当创建ServiceB并试图获取ServiceA时,由于ServiceA仍然在创建中,所以报错 if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } } protected void afterSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) { throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"); } } }

所以当使用构造方法注入时,Spring无法解决循环依赖。


总结,Spring自动解决循环依赖的条件:

  • 使用字段或set方法注入
  • bean的scope必须是singleton
  • 启用循环依赖支持(AbstractAutowireCapableBeanFactory.setAllowCircularReferences(boolean)),默认启用

同时,解决问题最好的办法就是避免发生问题,比如:在方法内通过BeanFactory.getBean()获取或者依赖的方法抽象出来放到第三个bean里。

相关代码(基于Spring 5.1.3.RELEASE)

https://github.com/dingfugui/spring-notes/tree/master/spring-circular-dependencies

点赞
收藏
评论区
推荐文章
阿里一线架构师技术图谱!十年开发经验Java架构师
开头我们面试的时候,经常会被问这种到问题:Spring中bean的循环依赖怎么解决?Spring中bean的加载过程?spring相关的问题一直是大厂面试常问到的一个问题,也是一直困扰这我们,不知道从哪里下手,今天举例分析大厂的一些spring相关的面试真题。和分享我学习spring相关问题所整理的一些知识点。01并发宝典:面试专题面试专题分为四个
Easter79 Easter79
2年前
tidb集群某个节点报错之:node_exporter
今天启动集群tidb时出现一个错误,是某个tikv节点报错:node\_exporter9100.service failed一个节点的问题会导致整个集群启动失败。去此节点下的日志文件中查找,发现没有什么报错原因。无奈此时只能去系统日志中查看发生了什么问题果然发现了问题Jan1615:35:05ip1723126133
0源码基础学习Spring源码系列(二)——Spring如何解决循环依赖
本篇文章适用于0基础学习spring源码,文章重点解析spring如何解决循环依赖,并从解决循环依赖过程、三级缓存在循环依赖中的作用、解决代理对象的问题、二级缓存、初始化几个维度出发,解析spring源码。
Easter79 Easter79
2年前
Spring中管理Bean依赖注入之后和Bean销毁之前的行为
    对于Singleton作用域的Bean,Spring容器将会跟踪它们的生命周期,容器知道何时实例化结束、何时销毁。Spring可以管理Bean在实例化结束之后和Bean销毁之前的行为。Bean依赖关系注入之后的行为:    Spring提供了两种方式在Bean全部属性设置成功后执行特定的行为:在Spring配置文件
Stella981 Stella981
2年前
Spring boot源码分析之Spring循环依赖揭秘
!(https://oscimg.oschina.net/oscnet/be79581de12c41704c44e976d329ad35ad1.gif)若你是一个有经验的程序员,那你在开发中必然碰到过这种现象:事务不生效。或许刚说到这,有的小伙伴就会大惊失色了。Spring不是解决了循环依赖问题吗,它是怎么又会发生循环依赖的呢?,接下来就
Easter79 Easter79
2年前
Spring循环依赖问题的解决
循环依赖问题一个bean的创建分为如下步骤:!(https://static.oschina.net/uploads/img/202102/24030007_IrhH.png)当创建一个简单对象的时候,过程如下:先从单例池中获取bean,发现无a创建a的实例为a赋值把a放到单例池
可莉 可莉
2年前
15张图带你彻底明白spring循环依赖,再也不用怕了
1.由同事抛的一个问题开始最近项目组的一个同事遇到了一个问题,问我的意见,一下子引起的我的兴趣,因为这个问题我也是第一次遇到。平时自认为对spring循环依赖问题还是比较了解的,直到遇到这个和后面的几个问题后,重新刷新了我的认识。我们先看看当时出问题的代码片段:@ServicepublicclassTestServic
Easter79 Easter79
2年前
Spring如何解决循环依赖的问题
        在关于Spring的面试中,我们经常会被问到一个问题,就是Spring是如何解决循环依赖的问题的。这个问题算是关于Spring的一个高频面试题,因为如果不刻意研读,相信即使读过源码,面试者也不一定能够一下子思考出个中奥秘。本文主要针对这个问题,从源码的角度对其实现原理进行讲解。1\.过程演示        关于Spring
京东云开发者 京东云开发者
8个月前
从源码层面深度剖析Spring循环依赖 | 京东云技术团队
本文从源码层面介绍了Spring如何创建bean、如何解决循环依赖,同时也介绍了不能解决哪些循环依赖,同时在文章的最后解决循环依赖报错的几个方法
京东云开发者 京东云开发者
4个月前
拓扑排序实现循环依赖判断 | 京东云技术团队
本文记录如何通过拓扑排序,实现循环依赖判断前言一般提到循环依赖,首先想到的就是Spring框架提供的Bean的循环依赖检测,相关文档可参考:https://blog.csdn.net/cristianoxm/article/details/11324610
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k