Directly hit the real question of Ali's Spring Recruitment: What is circular dependency? How to solve it with Spring?

Principle Analysis of Spring Circular Dependency

1. What is circular dependency? #

When we use Spring, one object is injected into another object, but the other object also contains the object. As shown in the figure:

A property of teacher is included in Student;

The property of student is included in Teacher. This creates a circular dependency.

2. Code description#

xml configuration file

testCycle.java

	private static void testCycle(){
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("cycle.xml");
		Teacher teacher = applicationContext.getBean(Teacher.class);
		System.out.println(teacher);
		Student student = applicationContext.getBean(Student.class);
		System.out.println(student);
	}

	public static void main(String[] args) {
		testCycle();
	}

Student.java

public class Student {
   private Teacher teacher;

   public Teacher getTeacher() {
      return teacher;
   }
   public void setTeacher(Teacher teacher) {
      this.teacher = teacher;
   }
}

Teacher.java

public class Teacher {

   private Student student;

   public Student getStudent() {
      return student;
   }
   public void setStudent(Student student) {
      this.student = student;
   }
}

3. Test results#

The teacher output here contains the student object, and the student object also contains the teacher object, and the contained objects are not null.

4. Why can circular dependency explain#

Give a picture first

When Spring creates beans, they must be created one by one. First of all, it will definitely go through a (Teacher/Student) life cycle. Take Teacher as an example here. When Spring goes to getBean(teacher), it will first go to the container to obtain it. If it cannot be obtained, it will create a teacher. When the teacher is created, it will assign a value to the attribute (student) of the teacher. In fact, There is no student object in the container. At this time, the student object will also be created. When the student is created, it will assign a value to the teacher attribute in the student. The teacher has been created before, and you can get it by going to getBean(teacher) at this time ( Note: At this time, the student attribute in the teacher is not assigned), so that the student is created, then it will return to the step of assigning the student attribute of the teacher. At this time, the student has been created and can be obtained with getBean(), so The teacher object is created. Then go back to the first step to create the student object, where the student object has been created when the teacher is created, and can be obtained directly using getBean(). The same is true when assigning a value to the property in the student, you can get the teacher directly. The circular dependency has since ended.

5. Question#

  1. How do I go to getBean() when I assign a value to the Student property of the Teacher?
  2. Why can getBean() get the teacher when assigning a value to the attribute teacher in the student?
  3. Why is the acquired teacher attribute injected for completion?

6. Source code explanation#

Overall method line#

First look at the source code:

getBean()->doGetBean()#

getBean()->doGetBean() is actually doGetBean to get the bean object

public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
      throws BeansException {

   return doGetBean(name, requiredType, args, false);
}

/**
 * Return an instance, which may be shared or independent, of the specified bean.
 * 返回指定 bean 的一个实例,该实例可以是共享的,也可以是独立的。
 */
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
      String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
      throws BeansException {

   // 转换beanName,FactoryBean的情况下beanName为&beanName,这里就是去掉&符号
   String beanName = transformedBeanName(name);
   Object beanInstance;

   // Eagerly check singleton cache for manually registered singletons.
   // 急切检查单例缓存从手动创建的单例中,获取bean判断是否存在当前beanName的bean
   Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null && args == null) {
      if (logger.isTraceEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
      				... 省略代码...
      }
      beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

   else {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      // 没有获取到,如果已经创建bean的实例,我们在一个循环引用中。当前的bean是否为正在创建中
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      // Check if bean definition exists in this factory.
      // 检查该工厂中是否存在bean的定义
      BeanFactory parentBeanFactory = getParentBeanFactory();
     ... 省略代码...
      if (!typeCheckOnly) {
         // 标记bean已经创建,正在创建
         markBeanAsCreated(beanName);
      }

      StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
            .tag("beanName", name);
      try {
         if (requiredType != null) {
            beanCreation.tag("beanType", requiredType::toString);
         }
         RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // Guarantee initialization of beans that the current bean depends on.
         // 保证当前的bean所依赖的bean已经初始化
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
            for (String dep : dependsOn) {
               if (isDependent(beanName, dep)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
               }
               registerDependentBean(dep, beanName);
               try {
                  getBean(dep);
               }
               catch (NoSuchBeanDefinitionException ex) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
               }
            }
         }

         // Create bean instance.
         // 创建bean的实例
         if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
               try {
                  return createBean(beanName, mbd, args);
               }
               catch (BeansException ex) {
                  // Explicitly remove instance from singleton cache: It might have been put there
                  // eagerly by the creation process, to allow for circular reference resolution.
                  // Also remove any beans that received a temporary reference to the bean.
                  // 从单例缓存中删除实例,它可能已经在这里
                  // 通过创建过程-允许循环引用解析
                  // 删除接收到任何对bean引用的临时bean
                  destroySingleton(beanName);
                  throw ex;
               }
            });
            beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }

         else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }

       ... 省略代码...
      finally {
         beanCreation.end();
      }
   }

   return adaptBeanInstance(name, beanInstance, requiredType);
}

The beanName passed in here is teacher

doGetBean()->createBean()#

look separately

// Create bean instance.
// 创建bean的实例
if (mbd.isSingleton()) {
   sharedInstance = getSingleton(beanName, () -> {
      try {
         return createBean(beanName, mbd, args);
      }
      catch (BeansException ex) {
         // Explicitly remove instance from singleton cache: It might have been put there
         // eagerly by the creation process, to allow for circular reference resolution.
         // Also remove any beans that received a temporary reference to the bean.
         // 从单例缓存中删除实例,它可能已经在这里
         // 通过创建过程-允许循环引用解析
         // 删除接收到任何对bean引用的临时bean
         destroySingleton(beanName);
         throw ex;
      }
   });
   beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

The important point here is that when the bean is not obtained, the createBean method will be called to create the bean. In the end, the doCreateBean method is actually used to create the bean.

createBean()->doCreateBean()#

Here comes the fourth part of the above method line

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   // BeanWrapper:持有创建出来的Bean
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      /**
       * 创建bean的实例
       * 实例化但是并未初始化,就是没有给bean的属性复制
       */
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   Object bean = instanceWrapper.getWrappedInstance();
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }

   // Allow post-processors to modify the merged bean definition.
   // 允许增强器修改合并的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能够解析循环引用
   // 即使生命周期接口触发像BeanFactoryAware,
   // 判断当前的bean是否需要提前曝光(加入singletonFactories缓存):bean是单例的&允许循环依赖&bean正在创建
   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");
      }
      // 将bean添加到singletonFactories  也就是说的三级缓存,但是这个地方的属性是没有赋值的
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }
       // 到这里,bean就已经实例化完成,并且将bean放入到了singletonFactories缓存中
   // Initialize the bean instance.
   // 初始化bean的实例
      Object exposedObject = bean;
   try {
      /**
       * 填充bean,填充Bean的属性
       */
      populateBean(beanName, mbd, instanceWrapper);
      /**
       * 去执行
       *     BeanPostProcessor的postProcessBeforeInitialization方法
       * */
      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 " +
                     "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
            }
         }
      }
   }

   // Register bean as disposable.
   // 将bean注册为一次性的
   try {
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }

   return exposedObject;
}

Explain the doCreateBean method separately

// Instantiate the bean.
   // BeanWrapper:持有创建出来的Bean
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      /**
       * 创建bean的实例
       * 实例化但是并未初始化,就是没有给bean的属性复制
       */
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }

Initialize the bean, this place starts to call the createBeanInstance method to create an instance of the bean

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 缓存单例的bean能够解析循环引用
// 即使生命周期接口触发像BeanFactoryAware,
// 判断当前的bean是否需要提前曝光(加入singletonFactories缓存):bean是单例的&允许循环依赖&bean正在创建
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");
   }
   // 将bean添加到singletonFactories  也就是说的三级缓存,但是这个地方的属性是没有赋值的
   addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

Remember the addSingletonFactory() method, which is the core of circular dependencies

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(singletonFactory, "Singleton factory must not be null");
   synchronized (this.singletonObjects) {
      if (!this.singletonObjects.containsKey(beanName)) {
         // 将beanName,singletonFactory放入到单例工厂的缓存【beanName-singletonFactory】
         this.singletonFactories.put(beanName, singletonFactory);
         // 从早起的单例对象缓存中移除【beanName-bean实例】
         this.earlySingletonObjects.remove(beanName);
         // 将beanName添加到已经注册的实例中
         this.registeredSingletons.add(beanName);
      }
   }
}

The singletonFactory stored here is a lambda expression, and the ObjectFactory is a functional interface. When the getObject method is executed, the stored getEarlyBeanReference(beanName, mbd, bean) will be called.

doCreateBean() -> createBeanInstance()#

There is not much to say here is to create the Teacher object through reflection

createBeanInstance() -> populateBean()#

Here is to start assigning values ​​to the created Teacher property student

/**
	 * Populate the bean instance in the given BeanWrapper with the property values
	 * from the bean definition.
	 * @param beanName the name of the bean
	 * @param mbd the bean definition for the bean
	 * @param bw the BeanWrapper with bean instance
	 * 允许属性值填充给BeanWrapper中的Bean实例
	 */
	@SuppressWarnings("deprecation")  // for postProcessPropertyValues  后处理属性值
	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		... 省略代码 ...
     // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the 给所有InstantiationAwareBeanPostProcessors有修改的机会
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		// 设置属性之前bean的状态,例如
		// 支持字段注入
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					return;
				}
			}
		}
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable. 通过名称自动注入参数的值
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable. 通过类型注入参数的值
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

		/**
		 * 有没有实例化的AwareBeanPostProcessor
		 */
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		/**
		 * 是否需要深度检查
		 */
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					return;
				}
				pvs = pvsToUse;
			}
		}
		if (needsDepCheck) {
			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		if (pvs != null) {
			// 应用给定的属性值,解决任何在这个bean工厂运行时它bean的引用。必须使用深copy。所以不会永久的修改此属性
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

separate parsing

if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					return;
				}
			}
		}  


The method postProcessAfterInstantiation of InstantiationAwareBeanPostProcessor, the return value of this method is boolean, if it returns true, it will do nothing, if it returns false, then this class will not be automatically assembled (attribute filling), here is the way we can pass the postprocessor Controls that certain beans are not populated with properties. It is obvious here that if we do not do special processing, the return of the innermost if here will not be executed.

	if (pvs != null) {
			// 应用给定的属性值,解决任何在这个bean工厂运行时它bean的引用。必须使用深copy。所以不会永久的修改此属性
			applyPropertyValues(beanName, mbd, bw, pvs);
		}

Here is the assignment to the student property of the Teacher

/**
 * Apply the given property values, resolving any runtime references
 * to other beans in this bean factory. Must use deep copy, so we
 * don't permanently modify this property.
 * @param beanName the bean name passed for better exception information
 * @param mbd the merged bean definition
 * @param bw the BeanWrapper wrapping the target object
 * @param pvs the new property values
 *  应用给定的属性值,解析对此 bean 工厂中其他 bean 的任何运行时引用。必须使用深拷贝,所以我们不会永久修改这个属性
 */
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
   if (pvs.isEmpty()) {
      // 如果pvs没有propertyValues,直接结束
      return;
   }

   MutablePropertyValues mpvs = null;
   List<PropertyValue> original;

   if (pvs instanceof MutablePropertyValues) {
      mpvs = (MutablePropertyValues) pvs;
      if (mpvs.isConverted()) {
         // Shortcut: use the pre-converted values as-is.
         try {
            bw.setPropertyValues(mpvs);
            return;
         }
         catch (BeansException ex) {
            throw new BeanCreationException(
                  mbd.getResourceDescription(), beanName, "Error setting property values", ex);
         }
      }
      original = mpvs.getPropertyValueList();
   }
   else {
      original = Arrays.asList(pvs.getPropertyValues());
   }

   TypeConverter converter = getCustomTypeConverter();
   if (converter == null) {
      converter = bw;
   }
   BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

   // Create a deep copy, resolving any references for values. 创建一个深copy,解析任何引用值
   List<PropertyValue> deepCopy = new ArrayList<>(original.size());
   boolean resolveNecessary = false;
   for (PropertyValue pv : original) {
      if (pv.isConverted()) {
         deepCopy.add(pv);
      }
      else {
         // 获取属性的名称
         String propertyName = pv.getName();
         // 获取属性的值
         Object originalValue = pv.getValue();
         if (originalValue == AutowiredPropertyMarker.INSTANCE) {
            Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
            if (writeMethod == null) {
               throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
            }
            originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
         }
         // 解析属性值
         Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
         Object convertedValue = resolvedValue;
         boolean convertible = bw.isWritableProperty(propertyName) &&
               !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
         if (convertible) {
            convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
         }
         // Possibly store converted value in merged bean definition,
         // in order to avoid re-conversion for every created bean instance.
         if (resolvedValue == originalValue) {
            if (convertible) {
               pv.setConvertedValue(convertedValue);
            }
            deepCopy.add(pv);
         }
         else if (convertible && originalValue instanceof TypedStringValue &&
               !((TypedStringValue) originalValue).isDynamic() &&
               !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
            pv.setConvertedValue(convertedValue);
            deepCopy.add(pv);
         }
         else {
            resolveNecessary = true;
            deepCopy.add(new PropertyValue(pv, convertedValue));
         }
      }
   }
   if (mpvs != null && !resolveNecessary) {
      mpvs.setConverted();
   }

   // Set our (possibly massaged) deep copy.
   try {
      bw.setPropertyValues(new MutablePropertyValues(deepCopy));
   }
   catch (BeansException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Error setting property values", ex);
   }
}

Parse attribute value

Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);

This will go directly to the resolveReference method

/**
 * Resolve a reference to another bean in the factory.解析对另一个bean的引用
 */
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
   try {
     	// 用来存放实例化出来的bean
			Object bean;
			// 获取bean的类型
      Class<?> beanType = ref.getBeanType();
      if (ref.isToParent()) {
         BeanFactory parent = this.beanFactory.getParentBeanFactory();
         if (parent == null) {
           ... 省略代码 ...
      }
      else {
         String resolvedName;
         if (beanType != null) {
            ... 省略代码... 
         }
         else {
            resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
            // 获取resolvedName的bean对象
            bean = this.beanFactory.getBean(resolvedName);
         }// 注册依赖的bean
         this.beanFactory.registerDependentBean(resolvedName, this.beanName);
      }
      if (bean instanceof NullBean) {
         bean = null;
      }
      return bean;
   }
   catch (BeansException ex) {
      throw new BeanCreationException(
            this.beanDefinition.getResourceDescription(), this.beanName,
            "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
   }
}

The method will go here to getBean() Before the getBean is finished, whether it has gone to getBean(), it is a nesting doll from here.

resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
            // 获取resolvedName的bean对象
            bean = this.beanFactory.getBean(resolvedName);
         }// 注册依赖的bean

When you get here, you will find an instance of Student, and you will go through the previous method, but when you go to the pupolate() method, you will assign a value to the teacher attribute of the student, and you will go to the container to get a teacher. Remember that there was a singletonFactories before. teacher? When you get it here, you will directly get the previously stored teacher. Take a look below

Omit the logic created before and go directly to the assignment operation

Here we start to get the teacher object, and see how the getSingleton() method is obtained;

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   // Quick check for existing instance without full singleton lock
   // 从单例对象缓存(singletonObjects--一级缓存)中获取bean对象
   Object singletonObject = this.singletonObjects.get(beanName);
   // 如果单例对象中没有找到,并且改bean正在创建中
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      // 从早期单例对象缓存中获取单例对象(之所以成为早期单例对象,是因为earlySingletonObjects里面
      // 的对象都是通过提前曝光的ObjectFactory创建出来的。还没有进行属性填充等操作)
      singletonObject = this.earlySingletonObjects.get(beanName);
      // 早期单例对象缓存(二级缓存)中也没有并且允许创建早期单例对象
      if (singletonObject == null && allowEarlyReference) {
         // 如果为空,则锁定全局变量进行处理
         synchronized (this.singletonObjects) {
            // Consistent creation of early reference within full singleton lock
            //在完整的单例锁中一致地创建早期引用
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               singletonObject = this.earlySingletonObjects.get(beanName);
               if (singletonObject == null) {
                  // 当某些方法需要提前初始化的时候则会调用addSingletonFactory方法将对应的objectFactory初始化策略储存在singletonFactories中
                  ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                  if (singletonFactory != null) {
                     // 如果存在单例对象工厂,则使用该工厂创建一个单例对象
                     singletonObject = singletonFactory.getObject();
                     // 创建的单例对象放如早期单例对象缓存中
                     this.earlySingletonObjects.put(beanName, singletonObject);
                     // 移除对应的单例对象工厂
                     this.singletonFactories.remove(beanName);
                  }
               }
            }
         }
      }
   }
   return singletonObject;
}

Here we get the lambda expression previously stored in singletonFactoriesMap, call the getObject() method to execute the getEarlyBeanReference method

/**
 * Obtain a reference for early access to the specified bean,
 * typically for the purpose of resolving a circular reference.
 * @param beanName the name of the bean (for error handling purposes)
 * @param mbd the merged bean definition for the bean
 * @param bean the raw bean instance
 * @return the object to expose as bean reference
 *
 * 获得对指定bean的早期访问的引用 通常用于解析循环依赖
 */
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
   // 默认最终公开的对象是bean,通过createBeanInstance创建出来的普通对象
   Object exposedObject = bean;
   // mbd的synthetic属性:设置bean定义是否是synthetic的,一般是指只有AOP相关的pointCut配置或者advice配置才会将synthetic设置为true
   // 如果mbd不是synthetic且此工厂拥有InstantiationAwareBeanPostProcessor
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      // 遍历工厂的所有后置处理器,并获取smartInstantiationAware-ArrayList
      for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
         // 让exposedObject对象经过每一个smartInstantiationAwareBeanPostProcessor报装
         exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
      }
   }
   // 返回最终经过层次报装后的对象
   return exposedObject;
}

There is no good explanation for this method, the comments clearly indicate the role of the method

After getting the teacher, assign a value to the teacher attribute in Student

resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));

After the Student object is created, the created Student object will be put into

try {
   // 去容器中获取bean对象
   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;
   }
   afterSingletonCreation(beanName);
}
if (newSingleton) {
   // 将beanName和singletonObject的映射关系添加到该工厂的单例缓存中
   addSingleton(beanName, singletonObject);
}

addSingleton(beanName, singletonObject); put in the cache

At this point, it will return to assign value to the student property in Teacher. At this point, the circular dependency is completed. Spring also went back to create the Student object, but this time, it can be directly taken out of the container.

Question answer#

Why do you have to create a Student object at the end, because you start to create a Student object because you need to use a Student instance when creating a Teacher object, so you create it once, but the last time you create a Student object, it will not really be created, directly It can be obtained from the cache singletonObjects.

Author: BaldHead

Source:
https://www.cnblogs.com/strict/p/15789451.html

If you think this article is helpful to you, you can retweet, follow and support

Guess you like

Origin blog.csdn.net/wdjnb/article/details/124282632
Recommended