Spring源码分析-bean创建(循环依赖)
Posted cao_xiaobo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring源码分析-bean创建(循环依赖)相关的知识,希望对你有一定的参考价值。
一、循环依赖产生的原因
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就结束了。
以上是关于Spring源码分析-bean创建(循环依赖)的主要内容,如果未能解决你的问题,请参考以下文章