在某一次面试中,对方问了一个问题: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在启动的时候,就把循环依赖处理掉了。于是跟踪查看源码:
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 { ... } } } }
获取所有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); } } } ... } } 尝试获取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; } } }
}
开始真正创建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; } } } ... } }
注入是通过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; } }
以方法注入为例,根据方法获取参数类型,并从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(); } } } } } 对于普通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