一、循环依赖产生的原因
A依赖B,B又依赖A
@Component
class A {
@Autowired
B b;
}
@Component
class B {
@Autowired
A a;
}
A类Bean创建过程:
- 先实例化A,(一般都是)通过无参构造完成实例化;
- A属性注入,发现A依赖B,准备B类Bean的创建;
- 实例化B,通过无参构造完成实例化;
- B属性注入,发现B依赖A,准备A类Bean的创建;
依次类推,就会产生一个死循环!好在spring已经为我们解决了这一问题。那么Spring中如何解决这个循环依赖的呢?
Spring解决循环依赖的核心方法有两个,一个是doGetBean中调用 getSingleton 方法,另一个是doCreateBean中调用addSingletonFactory 方法
二、源码分析
准备调试
(1)在DefaultListableBeanFactory.preInstantiateSingletons() 方法上进行断点调试,for循环断点过滤(beanName.equals("a") || beanName.equals("b"))
(2)在DefaultListableBeanFactory(AbstractBeanFactory).doGetBean方法上断点调试;第1次获取A的bean;第2次获取B的bean;第3次获取A的bean
下面是方法栈的信息:
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton 从singletonFactories拿到了这个A的bean
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean
DefaultListableBeanFactory(AbstractBeanFactory).getBean 6.获取属性A的bean
DependencyDescriptor.resolveCandidate
DefaultListableBeanFactory.doResolveDependency
DefaultListableBeanFactory.resolveDependency
AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject 5.对B中的带注解Autowired属性A注入
InjectionMetadata.inject
AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).populateBean
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean 4.创建B的bean(先实例化)
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean
AbstractBeanFactory$1.getObject()
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory<?>)
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean 3.获取属性B的bean
DefaultListableBeanFactory(AbstractBeanFactory).getBean
DependencyDescriptor.resolveCandidate
DefaultListableBeanFactory.doResolveDependency
DefaultListableBeanFactory.resolveDependency
AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject 2.对A中的带注解Autowired属性B注入
InjectionMetadata.inject
AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).populateBean
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean 1.创建A的bean(先实例化)
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean
AbstractBeanFactory$1.getObject()
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory<?>)
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean 断点调试 首次获取A的bean
通过方法栈,我画出了一个方法调用流程图
执行流程:
- doGetBean 首次获取A的bean,通过getSingleton方法获取A的bean,如果不存在,createBean;
- doCreateBean 开始创建A的bean,先实例化,接着判断是否需要提前暴露bean,这一步就提前暴露A的bean了,即向singletonFactories添加了A的bean操作,再调用populateBean方法进行属性注入;
- inject 对A中的带注解Autowired属性/方法 对B进行注入,最终又会调用getBean来获取B的bean;
- doGetBean 获取B的bean,此时,B因为是首次,所以又会对B的bean进行createBean操作;
- doCreateBean 开始创建B的bean,同样先实例化,判断是否需要提前暴露bean,再进行属性注入
- inject 对B中的带注解Autowired属性/方法 对A进行注入,最终又会调用getBean来获取A的bean;
- doGetBean 再次获取A的bean,这时候因为前面已经提前暴露过,所以A的Bean可以获取得到;
- inject 通过反射完成B的属性注入;
- doCreateBean 完成B的bean创建;
- inject 通过反射完成A的属性注入;
- doCreateBean 完成A的bean创建;
- 至此A的bean和B的bean都已经创建好了,下次轮到B来getBean时直接可以获取到。
(1)上面整体流程是这样的,但是在执行第7步的时候,是怎么获取到A的Bean的?下面我们来分析一下:
当第3次调用doGetBean方法时,也就是第2次获取A的bean时,当执行到 Object sharedInstance = getSingleton(beanName); 时,返回的不再是null了。
我们再来看一下getSingleton方法的功能:
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
// 关键点1,isSingletonCurrentlyInCreation方法
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 关键点2,singletonFactories单例工厂对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
- isSingletonCurrentlyInCreation,第1次调用获取A的bean的时候和第2次调用获取B的bean的时候返回都是false
- singletonFactories,第1次调用获取A的bean的时候值为null,第一次调用获取B的bean的时候,里面就包含A的信息...
(2)singletonFactories 这个对象是什么鬼?
从上述代码上可以看出singletonFactories是一个临时存放bean实例的工厂池,当拿到了bean只后就会把相就的bean从这个临时的工厂池删除掉。
那这个A的这个bean实例是什么时候存放进去的?
当执行addSingletonFactory方法时,会向singletonFactories中设值
在doCreateBean方法bean实例化之后,会执行相关的addSingletonFactory 方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final 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 != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
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) {
// 抛出异常...
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// ********************** singletonFactories 设值的关键部分 START **********************
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
// isSingletonCurrentlyInCreation也是一个关键方法,与getSingleton方法相呼应
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// ********************** singletonFactories 设值的关键部分 END **********************
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable 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<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
// 抛出异常。。。
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
总结:当循环依赖存在的时候,会一直循环调用doGetBean方法(ABABAB)...,Spring为我们解决了这一问题,使得doGetBean方法为ABA就结束了。