spring source code-fourth post processor

This is the source code study notes for the
fourth post-processor. The fourth post-processor is mainly for supporting circular dependencies.

org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference

This is the method name of the fourth post processor. In the spring source code, there are only two beanPostProcessors that implement this method. They are:

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getEarlyBeanReference

org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter#getEarlyBeanReference

Among them, the getEarlyBeanReference() method of InstantiationAwareBeanPostProcessorAdapter does nothing, but returns the bean intact. The
main function is here in AbstractAutoProxyCreator#getEarlyBeanReference

Let's first look at the code of this method

@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
    
    
  Object cacheKey = getCacheKey(bean.getClass(), beanName);
  if (!this.earlyProxyReferences.contains(cacheKey)) {
    
    
    this.earlyProxyReferences.add(cacheKey);
  }
  return wrapIfNecessary(bean, beanName, cacheKey);
}

There are only a few lines of code, but you will find that these lines of code are actually what the eighth post processor (generating dynamic proxy objects) does;

Next we look at the logic of the outer layer of the fourth post processor

/**
 * 第四个后置处理器执行的前提条件是:
 * 1.当前bean是单实例的
 * 2.当前beanFactory允许循环依赖:allowCircularReferences这个参数没找到在哪个扩展点中可以改为false,初始化默认是true,所以我们姑且认为大部分情况下这个参数都是true
 * 3.当前bean正在创建中,这里是判断是否在一个集合中
 * singletonsCurrentlyInCreation会在开始初始化之前,判断当前bean是单实例的时候,加入到集合中
 */
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
    
    
  if (logger.isDebugEnabled()) {
    
    
    logger.debug("Eagerly caching bean '" + beanName +
        "' to allow for resolving potential circular references");
  }
  /**
   * mpy 第四次调用后置处理器 获取一个提前暴露的对象 objectFactory 用来解决循环依赖
   * 这里还有一个关键的作用,可以追进去看一下,这里可能会完成动态代理对象的生成(AOP)
   * 正常情况下,AOP的动态代理是在调用org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)的时候,才会生成(也即:第八个后置处理器)
   * 但是,如果是循环依赖的话,会在 org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference(java.lang.Object, java.lang.String) 中完成
   *
   * 所以:对于循环依赖,这里提前暴露的对象,虽然没有完成后面的初始化方法的解析(invokeInitMethod),但是完成了动态代理对象的生成
   *
   * 这里getEarlyBeanReference();不会立即执行,而是在从二级缓存中获取对象的时候,会调用该方法,在该方法中完成动态代理
   *
   */
  addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

/**
 * 这里是第四个后置处理器的逻辑
 * 在这里,会把第四个后置处理器作为一个ObjectFactory存入到一个map集合中
 * 所以这个后置处理器,并不会立即执行,而是在从map取出来的时候,会被执行,那什么时候会被取出来呢?
 * 在循环依赖中
 * Add the given singleton factory for building the specified singleton
 * if necessary.
 * <p>To be called for eager registration of singletons, e.g. to be able to
 * resolve circular references.
 * @param beanName the name of the bean
 * @param singletonFactory the factory for the singleton object
 */
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    
    
  Assert.notNull(singletonFactory, "Singleton factory must not be null");
  synchronized (this.singletonObjects) {
    
    
    /**
     * 这里会加一层判断,如果单实例池中已经有bean对象了,就无须再插入到singletonFactories中,此时也就不存在
     * 循环依赖的问题了
     */
    if (!this.singletonObjects.containsKey(beanName)) {
    
    
      this.singletonFactories.put(beanName, singletonFactory);
      this.earlySingletonObjects.remove(beanName);
      this.registeredSingletons.add(beanName);
    }
  }
}

The logic here is these few lines of code, mainly for the attribute circular dependency, then when will the fourth post processor be called?

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
	org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)

/**
 *
 * singletonObjects是spring单实例池
 * 我们暂时称
 *   earlySingletonObjects为三级缓存  该map是在后面进行判断,是否允许循环依赖,如果允许,就把bean存到这个map中
 *   singletonFactories为二级缓存  在判断是单实例bean的时候,将包含bean的beanFactory存到该map中,这个map中存储的是一个生成代理对象的factory
 *   singletonObjects为一级缓存,存储的是实例化之后的bean
 *
 *   在这里,三级缓存的map保存的是从二级缓存中取到的一个对象,取到之后,从二级缓存中将bean删除
 *   这样做是为了防止重复创建,
 *
 *   在获取到依赖的对象之后,会进行一次类型校验 org.springframework.beans.factory.support.AbstractBeanFactory#isTypeMatch(java.lang.String, org.springframework.core.ResolvableType)
 *
 *   循环依赖的处理:
 *    如果A注入了B,B也注入了A;在第一次实例化A的时候,会注入A,注入A的时候,会反过来去实例化B
 */
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    
    
  Object singletonObject = this.singletonObjects.get(beanName);
  if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    
    
    synchronized (this.singletonObjects) {
    
    
      //mpy 这里只需要从二级缓存中拿一次就行,如果没有二级缓存,每次进来都需要从二级缓存get一次,影响效率
      singletonObject = this.earlySingletonObjects.get(beanName);
      if (singletonObject == null && allowEarlyReference) {
    
    
        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
        if (singletonFactory != null) {
    
    
          /**
           * 这里getObject会调用getEarlyBeanReference(beanName, mbd, bean)方法,完成动态代理对象的生成
           * 这里为什么要调用这个方法?
           * 我的理解是这样的:在属性注入之后,还有两个后置处理器需要调用:
           *  1.applyBeanPostProcessorsBeforeInitialization   invokeInitMethod方法,也即:调用bean的初始化方法的后置处理器
           *  2.applyBeanPostProcessorsAfterInitialization  这里完成的是:代理对象的生成(比如:AOP动态代理对象生成,事务方法代理对象生成)
           *
           * 既然有了循环依赖,总要有一个bean是要先注入的,在注入
           */
          singletonObject = singletonFactory.getObject();
          this.earlySingletonObjects.put(beanName, singletonObject);
          this.singletonFactories.remove(beanName);
        }
      }
    }
  }
  return singletonObject;
}

That's it, so we say that the fourth post-processor is to complete the processing of circular dependencies;
in the case where A depends on B and B depends on A, first complete the generation of dynamic proxy objects for the A object, and then after injection, Then execute attribute injection, initialization method callback and other methods; in fact, there is one point that I don’t understand. Why in circular dependencies, we must first complete the generation of dynamic proxy objects when injecting beans?

Guess you like

Origin blog.csdn.net/CPLASF_/article/details/111585286