Spring是如何解决循环依赖的

​ 在某一次面试中,对方问了一个问题: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 {
                ...
            }
        }
    }
}
  1. 获取所有bean名字,当bean满足非抽象、单例、非延迟初始化条件时,调用getBean()触发bean初始化。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
	@Override
	public void preInstantiateSingletons() throws BeansException {
		...
		List<String> 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<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext());
                        } else {
                            isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit());
                        }
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
				} else {
					// 不是FactoryBean,普通bean
					getBean(beanName);
				}
			}
		}
		...
	}
}
  1. 尝试获取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;
            }
        }
    }
}
  1. 开始真正创建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;
                }
            }
        }
		...
    }
}
  1. 注入是通过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;
    }
}
  1. 以方法注入为例,根据方法获取参数类型,并从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<String> 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();
				}
			}
		}
	}
}
  1. 对于普通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> 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;

        // 由于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<String> 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

转载于:https://my.oschina.net/u/1013857/blog/3013184

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值