Spring中的循环依赖

  • 首先需要说明的是Spring默认是允许循环依赖的,当然可以通过DefaultListxxxx.setCircle(false)让容器不允许循环依赖。

  • 其次,循环依赖只能通过set来设置,不能通过构造方法。而且不能是原型模式,必须是单例。其实说白了就是一个属性注入。

  • 最后,描述一下Spring中getBean的大致流程:从容器中拿---验证---创建(从容器中再拿一次)

  • 就从refresh方法一步一步开扣,refresh中的finishBeanFactoryInitialization(beanFactory)--->beanFactory.preInstantiateSingletons();------>getBean(beanName);---->doGetBean(name, null, null, false);
    好了,暂停开扣,补水:Object sharedInstance = getSingleton(beanName);doGetBean中首先会从单例池中先取一遍,第一次取当然为null不用想。

getSingleton代码
Object singletonObject = this.singletonObjects.get(beanName);//这里第一次取的时候为null
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName));//判断当前的Bean是不是正在被创建,这里是第一次来创建,当然也是FALSE
之后在doGetBean中又进行了一系列的判断,后面就要开始真正的创建Bean了:
点击查看代码
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
	try {
			return createBean(beanName, mbd, args);
		}
		catch (BeansException ex) {

		}
	});
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
  • 需要注意的是,此时也是调用了getSingleton的另一个重载方法,在该方法中首先会对Bean进行标记,beforeSingletonCreation(beanName);这个方法中就会把当前创建的BeanName放到singletonsCurrentlyInCreation这个Map中,这就和之前的一步关联起来了,这里先按下不表。

  • 之后就会调用createBean来创建Bean的实例,接连调用doCreateBean--->createBeanInstance方法,里面干了两件事,一是通过后置处理器(第二次调用后置处理器,如果说有多个质疑的才会有,只有一个的情况为NULL)来推断构造方法,二是对Bean进行实例化。

  • 在doCreateBean的applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);方法中第三次调用后置处理器, addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));方法中第四次调用后置处理器,判断是否需要AOP。

  • 其中在createBean方法中Object bean = resolveBeforeInstantiation(beanName, mbdToUse);第一次调用了后置处理器(AOP位置)

循环引用的开始是populateBean方法中的属性注入。

populateBean
// 一般为true,进入
		if (hasInstAwareBpps) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					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;
				}
			}
		}
- 其中getBeanPostProcessors()可以发现有6个bean后置处理器。AutowiredAnnotationbeanPostProcessor是专门用来处理@Autowired注解,Common开头的专门用来处理@Resource注解。,然后兜兜转转又到了GetBean。
posted @ 2021-10-13 15:30  莫西123  阅读(284)  评论(0)    收藏  举报