在某一次面试中,对方问了一个问题:Spring的Bean如果互相依赖,会发生什么?由于我那段时间正好遇到了一个Spring循环依赖报错的问题,就回答会报错。然后听对方口气,感觉自己答错了。于是事后了解了一下,才发现其实Spring自身解决了循环依赖的问题。
Spring的启动后,会读取配置文件,资源文件读取校验,创建BeanFactory,解析配置文件创建BeanDefinition,注册到BeanFactory,注册各种默认处理器,加载国际化、事件广播、监听器等,最后实例化非延迟初始化的单例。
代码关键点如下:
1AbstractApplicationContext.refresh() //加载配置,启动容器 2 3 AbstractApplicationContext.finishBeanFactoryInitialization() 4 5 DefaultListableBeanFactory.preInstantiateSingletons() //实例化单例 6 7 AbstractBeanFactory.getBean() //获取bean,触发创建 8 9 AbstractBeanFactory.doGetBean() 10 11 DefaultSingletonBeanRegistry.getSingleton() //获取bean触发bean的创建并缓存 12 13 AbstractAutowireCapableBeanFactory.createBean() //InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()提前创建bean 14 15 AbstractAutowireCapableBeanFactory.doCreateBean() //创建bean 16 17 AbstractAutowireCapableBeanFactory.populateBean() //注入 18 19 AbstractAutowireCapableBeanFactory.initializeBean() //初始化,afterPropertiesSet、initMethod、Aware注入、postProcessAfterInitialization()
以一个简单循环依赖为例,两个普通的互相依赖的Bean(非延迟初始化的单例)。
1@Component 2public class ServiceA { 3 private ServiceB serviceB; 4 public ServiceA() { 5 System.out.println("ServiceA()"); 6 } 7 public void foo() { 8 System.out.println("serviceA.foo()"); 9 serviceB.foo(); 10 } 11 @Autowired 12 public void setServiceB(ServiceB serviceB) { 13 System.out.println("serviceA.setServiceB()"); 14 this.serviceB = serviceB; 15 } 16} 17@Component 18public class ServiceB { 19 private ServiceA serviceA; 20 public ServiceB() { 21 System.out.println("serviceB()"); 22 } 23 public void foo() { 24 System.out.println("serviceB.foo()"); 25 } 26 @Autowired 27 public void setServiceA(ServiceA serviceA) { 28 System.out.println("serviceB.setServiceA()"); 29 this.serviceA = serviceA; 30 } 31} 32@Configuration 33@ComponentScan 34public class SetMain { 35 public static void main(String[] args) { 36 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainApplication.class); 37 System.out.println("start"); 38 context.getBean(ServiceA.class).foo(); 39 } 40}
执行后,会打印
1ServiceA() 2ServiceB() 3serviceB.setServiceA() 4serviceA.setServiceB() 5start 6serviceA.foo() 7serviceB.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();
1 // Tell the subclass to refresh the internal bean factory. 2 // 解析配置,创建Beanfactory 3 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 4 5 // Prepare the bean factory for use in this context. 6 // 配置BeanFactory,例如默认ClassLoader和各种处理器 7 prepareBeanFactory(beanFactory); 8 9 try { 10 // Allows post-processing of the bean factory in context subclasses. 11 // 允许在上下文子类中对bean工厂进行后处理。 12 postProcessBeanFactory(beanFactory); 13 14 // Invoke factory processors registered as beans in the context. 15 // 执行所有注册为bean的BeanFactoryPostProcessor 16 invokeBeanFactoryPostProcessors(beanFactory); 17 18 // Register bean processors that intercept bean creation. 19 // 注册BeanPostProcessor bean 20 registerBeanPostProcessors(beanFactory); 21 22 // Initialize message source for this context. 23 // 初始化MessageSource,用于国际化 24 initMessageSource(); 25 26 // Initialize event multicaster for this context. 27 // 初始化事件广播 28 initApplicationEventMulticaster(); 29 30 // Initialize other special beans in specific context subclasses. 31 // 初始化特定上下文子类中的其他特殊bean。 32 onRefresh(); 33 34 // Check for listener beans and register them. 35 // 检查监听器bean并注册它们 36 registerListeners(); 37 38 // Instantiate all remaining (non-lazy-init) singletons. 39 // 实例化所有剩余的(非延迟初始化)单例 40 finishBeanFactoryInitialization(beanFactory); 41 42 // Last step: publish corresponding event. 43 finishRefresh(); 44 } catch (BeansException ex) { 45 ... 46 } finally { 47 ... 48 } 49 } 50}}
-
获取所有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);
1 // Trigger initialization of all non-lazy singleton beans... 2 for (String beanName : beanNames) { 3 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); 4 // 非抽象、单例、非延迟初始化 5 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { 6 if (isFactoryBean(beanName)) { 7 Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); 8 if (bean instanceof FactoryBean) { 9 final FactoryBean<?> factory = (FactoryBean<?>) bean; 10 boolean isEagerInit; 11 if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { 12 isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); 13 } else { 14 isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); 15 } 16 if (isEagerInit) { 17 getBean(beanName); 18 } 19 } 20 } else { 21 // 不是FactoryBean,普通bean 22 getBean(beanName); 23 } 24 } 25 } 26 ... 27}}
-
尝试获取bean,如果取不到,就创建
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
1protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { 2 final String beanName = transformedBeanName(name); 3 Object bean; 4 5 // Eagerly check singleton cache for manually registered singletons. 6 // 急切地检查单例缓存以手动注册单例。 7 Object sharedInstance = getSingleton(beanName); 8 if (sharedInstance != null && args == null) { 9 if (logger.isTraceEnabled()) { 10 if (isSingletonCurrentlyInCreation(beanName)) { 11 logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); 12 } else { 13 logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); 14 } 15 } 16 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); 17 } else { 18 // 获取不到,bean没有被创建 19 20 // Fail if we're already creating this bean instance: We're assumably within a circular reference. 21 // 如果我们已经在创建这个bean实例,则失败: 我们假设在一个循环引用中。 22 if (isPrototypeCurrentlyInCreation(beanName)) { 23 throw new BeanCurrentlyInCreationException(beanName); 24 } 25 26 // Check if bean definition exists in this factory. 27 // 从parent中获取bean 28 BeanFactory parentBeanFactory = getParentBeanFactory(); 29 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 30 // Not found -> check parent. 31 String nameToLookup = originalBeanName(name); 32 if (parentBeanFactory instanceof AbstractBeanFactory) { 33 return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly); 34 } else if (args != null) { 35 // Delegation to parent with explicit args. 36 return (T) parentBeanFactory.getBean(nameToLookup, args); 37 } else if (requiredType != null) { 38 // No args -> delegate to standard getBean method. 39 return parentBeanFactory.getBean(nameToLookup, requiredType); 40 } else { 41 return (T) parentBeanFactory.getBean(nameToLookup); 42 } 43 } 44 45 if (!typeCheckOnly) { 46 markBeanAsCreated(beanName); 47 } 48 49 try { 50 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 51 checkMergedBeanDefinition(mbd, beanName, args); 52 53 // Guarantee initialization of beans that the current bean depends on. 54 // 处理@DependsOn 55 String[] dependsOn = mbd.getDependsOn(); 56 if (dependsOn != null) { 57 for (String dep : dependsOn) { 58 if (isDependent(beanName, dep)) { 59 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); 60 } 61 registerDependentBean(dep, beanName); 62 try { 63 getBean(dep); 64 } catch (NoSuchBeanDefinitionException ex) { 65 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 66 "'" + beanName + "' depends on missing bean '" + dep + "'", ex); 67 } 68 } 69 } 70 71 // Create bean instance. 72 // 创建bean实例 73 if (mbd.isSingleton()) { 74 // 获取/创建 75 sharedInstance = getSingleton(beanName, () -> { 76 try { 77 return createBean(beanName, mbd, args); 78 } catch (BeansException ex) { 79 ... 80 } 81 }); 82 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 83 } 84 ... 85 } catch (BeansException ex) { 86 cleanupAfterBeanCreationFailure(beanName); 87 throw ex; 88 } 89 } 90}}
-
开始真正创建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; }
1protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { 2 ... 3 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); 4 boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); 5 6 PropertyDescriptor[] filteredPds = null; 7 if (hasInstAwareBpps) { 8 if (pvs == null) { 9 pvs = mbd.getPropertyValues(); 10 } 11 for (BeanPostProcessor bp : getBeanPostProcessors()) { 12 if (bp instanceof InstantiationAwareBeanPostProcessor) { 13 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; 14 //ImportAwareBeanPostProcessor、AutowiredAnnotationBeanPostProcessor 15 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); 16 if (pvsToUse == null) { 17 if (filteredPds == null) { 18 filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); 19 } 20 pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); 21 if (pvsToUse == null) { 22 return; 23 } 24 } 25 pvs = pvsToUse; 26 } 27 } 28 } 29 ... 30}}
-
注入是通过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<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(); } } } } }
-
对于普通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对象。
1public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { 2 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { 3 BeanWrapper instanceWrapper = null; 4 if (mbd.isSingleton()) { 5 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); 6 } 7 if (instanceWrapper == null) { 8 instanceWrapper = createBeanInstance(beanName, mbd, args); 9 } 10 //刚new的对象 11 final Object bean = instanceWrapper.getWrappedInstance(); 12 ... 13 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); 14 if (earlySingletonExposure) { 15 if (logger.isTraceEnabled()) { 16 logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); 17 } 18 //设置单例工厂,设置singletonFactories,把bean传入 19 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 20 } 21 ... 22 } 23 protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { 24 Object exposedObject = bean; 25 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { 26 for (BeanPostProcessor bp : getBeanPostProcessors()) { 27 if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { 28 //默认情况全部返回bean,不做修改 29 SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; 30 exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); 31 } 32 } 33 } 34 return exposedObject; 35 } 36} 37public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { 38 protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { 39 Assert.notNull(singletonFactory, "Singleton factory must not be null"); 40 synchronized (this.singletonObjects) { 41 if (!this.singletonObjects.containsKey(beanName)) { 42 // 第一次创建ServiceA时,保存ObjectFactory 43 this.singletonFactories.put(beanName, singletonFactory); 44 this.earlySingletonObjects.remove(beanName); 45 this.registeredSingletons.add(beanName); 46 } 47 } 48 } 49}
当ServiceB尝试获取ServiceA时,就会从singletonFactories中获取ObjectFactory,调用工厂获取之前放入的ServiceA对象。所以这里会直接返回新创建且没有初始化的ServiceA(serviceB=null)对象,并注入到ServiceB中。ServiceB初始化完成之后,将返回ServiceB(serviceA=servieA(serviceB=null))对象注入到ServiceA中,此时ServiceB(serviceA=servieA(serviceB=serviceB))中的ServiceA对象也就包含了ServiceB的引用了。至此,循环依赖就完成了。
1public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { 2 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { 3 final String beanName = transformedBeanName(name); 4 Object bean; 5 // Eagerly check singleton cache for manually registered singletons. 6 // 急切地检查单例缓存以手动注册单例。 7 Object sharedInstance = getSingleton(beanName); 8 if (sharedInstance != null && args == null) { 9 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); 10 } 11 ... 12 } 13} 14public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { 15 public Object getSingleton(String beanName) { 16 return getSingleton(beanName, true); 17 } 18 protected Object getSingleton(String beanName, boolean allowEarlyReference) { 19 Object singletonObject = this.singletonObjects.get(beanName); 20 //第一次,返回false,执行创,DefaultSingletonBeanRegistry.getSingleton(String,ObjectFactory)#beforeSingletonCreation保存了beanName 21 //第二次,返回true 22 //bena创建完成后从singletonObjects能直接获取 23 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { 24 // 如果获取不到,且实例正在创建中 25 synchronized (this.singletonObjects) { 26 singletonObject = this.earlySingletonObjects.get(beanName); 27 // 如果还没创建出来 28 if (singletonObject == null && allowEarlyReference) { 29 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); 30 if (singletonFactory != null) { 31 // 调用工厂创建,AbstractAutowireCapableBeanFactory.doCreateBean()#addSingletonFactory()设置的 32 singletonObject = singletonFactory.getObject(); 33 this.earlySingletonObjects.put(beanName, singletonObject); 34 this.singletonFactories.remove(beanName); 35 } 36 } 37 } 38 } 39 return singletonObject; 40 } 41 private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16)); 42 public boolean isSingletonCurrentlyInCreation(String beanName) { 43 return this.singletonsCurrentlyInCreation.contains(beanName); 44 } 45}
这个功能的要点就在DefaultSingletonBeanRegistry.getSingleton()中,当创建ServiceA时,会把ObjectFactory放入singletonFactories中,当创建ServiceB需要注入ServiceA时,获得ObjectFactory,拿到ServiceA对象,并放入earlySingletonObjects中,这个过程中有其他bean依赖ServiceA就可以直接从earlySingletonObjects获取。当ServiceA初始化过程完成,把bean放入singletonObjects,当其他bean依赖ServiceA时,直接从singletonObjects中获取。
可见,Spring解决了循环依赖问题,那为什么我会遇到报错呢。因为我接手了IDE的建议,把注入方式改成了构造方法注入。
1@Component 2public class ServiceA { 3 private final ServiceB serviceB; 4 5 @Autowired 6 public ServiceA(ServiceB serviceB) { 7 System.out.println("ServiceA()"); 8 this.serviceB = serviceB; 9 } 10 11 public void foo() { 12 System.out.println("serviceA.foo()"); 13 serviceB.foo(); 14 } 15} 16@Component 17public class ServiceB { 18 private final ServiceA serviceA; 19 20 @Autowired 21 public ServiceB(ServiceA serviceA) { 22 System.out.println("ServiceB()"); 23 this.serviceA = serviceA; 24 } 25 26 public void foo() { 27 System.out.println("serviceB.foo()"); 28 } 29} 30@Configuration 31@ComponentScan 32public class ConstructorMain { 33 public static void main(String[] args) { 34 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConstructorMain.class); 35 System.out.println("start"); 36 context.getBean(ServiceA.class).foo(); 37 } 38}
执行后Spring启动报错,告知依赖的bean正在创建中,可能有循环引用
1Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'serviceA': Requested bean is currently in creation: Is there an unresolvable circular reference? 2 at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:374) 3 at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:250) 4 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) 5 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192) 6 at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:273) 7 at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1247) 8 at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1177) 9 at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:857) 10 at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:760) 11 ... 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 {
1 final String beanName = transformedBeanName(name); 2 Object bean; 3 4 // 由于ServiceA尚未初始化,所以这里取不到 5 Object sharedInstance = getSingleton(beanName); 6 if (sharedInstance != null && args == null) { 7 ... 8 } else { 9 try { 10 ... 11 // 创建 12 if (mbd.isSingleton()) { 13 sharedInstance = getSingleton(beanName, () -> { 14 try { 15 return createBean(beanName, mbd, args); 16 } catch (BeansException ex) { 17 ... 18 } 19 }); 20 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 21 ... 22 } 23 } catch (BeansException ex) { 24 cleanupAfterBeanCreationFailure(beanName); 25 throw ex; 26 } 27 } 28 ... 29 return (T) bean; 30}}
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