serviceA里注入了serviceB,serviceB里又注入了serviceA,这样在实例化serviceA时,在doCreateBean时的populateBean时会先实例化serviceB,然后实例化serviceB,在serviceB的doCreateBean方法的populateBean又会去找servcieA,这样循环依赖就产生了。
解决办法就是在populateBean之前把当前的serviceA提前暴露,然后在实例化B时可以找到这个提前暴露的serviceA。
关键方法是doCreateBean方法中的addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
1. DefaultSingletonBeanRegistry#getSingleton
这里就是对当前bean做了一个标志,在实例化前表明当前bean在创建中,在实例化后删除这个标志
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) {if (this.singletonsCurrentlyInDestruction) {throw new BeanCreationNotAllowedException(beanName,"Singleton bean creation not allowed while singletons of this factory are in destruction " +"(Do not request a bean from a BeanFactory in a destroy method implementation!)");}if (logger.isDebugEnabled()) {logger.debug("Creating shared instance of singleton bean '" + beanName + "'");}//关键1 标志A这个Bean在创建中beforeSingletonCreation(beanName);boolean newSingleton = false;boolean recordSuppressedExceptions = (this.suppressedExceptions == null);if (recordSuppressedExceptions) {this.suppressedExceptions = new LinkedHashSet<>();}try {//调用createBean方法singletonObject = singletonFactory.getObject();newSingleton = true;}catch (IllegalStateException ex) {// Has the singleton object implicitly appeared in the meantime ->// if yes, proceed with it since the exception indicates that state.singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {throw ex;}}catch (BeanCreationException ex) {if (recordSuppressedExceptions) {for (Exception suppressedException : this.suppressedExceptions) {ex.addRelatedCause(suppressedException);}}throw ex;}finally {if (recordSuppressedExceptions) {this.suppressedExceptions = null;}//关键2 //this.singletonsCurrentlyInCreation.remove(beanName)//删除掉Bean A创建中的标识afterSingletonCreation(beanName);}if (newSingleton) {addSingleton(beanName, singletonObject);}}return singletonObject;}}
2. AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.//这里如果是单例 并且允许循环依赖 并且是正在创建的bean(1中设置)//能满足这个三个条件,则Spring会认为这个此时A是需要提前暴漏的单例Beanboolean 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 {populateBean(beanName, mbd, instanceWrapper);exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");}}}}// Register bean as disposable.try {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;}
3. DefaultSingletonBeanRegistry#addSingletonFactory
实例化A时,doCreateBean方法populateBean方法执行之前,也就是实例化注入的serviceB之前会调用这个方法。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {Assert.notNull(singletonFactory, "Singleton factory must not be null");synchronized (this.singletonObjects) {if (!this.singletonObjects.containsKey(beanName)) {//把当前bean 也就是serviceA关联一个singletonFactory(也就是那个lambda表达式)this.singletonFactories.put(beanName, singletonFactory);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}}}
给A关联了一个ObjectFactory,也就是getEarlyBeanReference对应的lambda函数对象。放入了singletonFactories中,当B去查BeanA的时候就可以通过getEarlyBeanReference方法获取exposedObject这个早期bean对象。
4.AbstractAutowireCapableBeanFactory#getEarlyBeanReference
这里基本就是把传入的bean返回。命名为exposedObject 早期暴露对象
调用逻辑就是 serviceB实例化时需要注入serviceA,然后在doGetBean的最开始调用getSingleton方法时会获取到serviceA的ObjectFactory,然后执行singletonFactory.getObject()就会执行这个方法拿到bean。
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {Object exposedObject = bean;if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);}}}return exposedObject;}
查找
比如在实例化serviceA时需要实例化serviceB,实例化serviceB时populateBean方法会再尝试实例化serviceA,doGetBean方法开始会调用getSingleton方法,这个方法里会找到提前暴露的serviceA,保证serviceB可以顺利创建。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {//这里获取不到 因为servcieA的实例化还没完成 也就是servcieA的createBean方法还没执行完,servcieA的getSingleton方法的//singletonObject = singletonFactory.getObject()方法也就没执行完,下面的addSingleton方法//就不会执行(在这里执行this.singletonObjects.put(beanName, singletonObject)), //singletonObjects中就不会有serviceA。Object singletonObject = this.singletonObjects.get(beanName);//判断会通过 第二个判断条件是在getSingleton方法的beforeSingletonCreation(beanName)设置的 最开始实例化A时会调用if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {//这里也获取不到,因为在最开始servcieA实例化时的addSingletonFactory方法会执行//this.earlySingletonObjects.remove(beanName);singletonObject = this.earlySingletonObjects.get(beanName);//判断会进入if (singletonObject == null && allowEarlyReference) {//这里能获取到,因为在servcieA实例化时的addSingletonFactory方法会执行//this.singletonFactories.put(beanName, singletonFactory);ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {//执行这个方法会执行那个lambda表达式 () -> getEarlyBeanReference(beanName, mbd, bean)//获取到serviceAsingletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}//获取到返回 此时serviceB就可以得到serviceA了,然后继续创建serviceBreturn singletonObject;}
总结
实例化过程:
1.finishBeanFactoryInitialization(beanFactory);
2.beanFactory.preInstantiateSingletons();
3.getBean(beanName);
4.doGetBean
这里实例化serviceA时找不到,但是在实例化注入的serviceB时又需要实例化serviceB注入的serviceA,这时就可以获取到
serviceA了。
5.
这里的getSingleton方法在执行时执行到**singletonObject = singletonFactory.getObject()**时就会执行lambda表达式的createBean方法。
依赖关系的处理是在createBean方法的doCreateBean方法的populateBean方法
6.doCreateBean
关键方法
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
这个方法在实例化serviceA,populateBean之前,把serviceA及关联的ObjectFactory(lambda表达式)加到了singletonFactories,这样serviceB实例化时需要实例化servcieA,在doGetBean一开始的getSingleton方法会获取到serviceA,这样就能保证serviceB能创建完成,然后再创建serviceA。