0
点赞
收藏
分享

微信扫一扫

spring bean的循环依赖完全掌握

水墨_青花 2022-02-19 阅读 58

一. 明确需要搞清楚的问题

  1. 普通bean的非循环依赖bean生命周期的流程
  2. aop代理bean的非循环依赖的bean生命周期的流程
  3. 普通bean的循环依赖bean生命周期的流程
  4. aop代理bean的循环依赖bean生命周期的流程

搞清楚四个问题, 再回答spring的bean的循环依赖, 易如反掌

循序渐进的理解也便于对比, 容易理解

二. 普通bean的非循环依赖bean生命周期的流程

1. 获取bean

AbstractApplicationContext#getBean(“a”, A.class)

AbstractBeanFactory#doGetBean(“a”, A.class)

DefaultSingletonBeanRegistry#getSingleton(“a”, true) // 尝试从缓存中获取, true表示允许提前从工厂池中获取引用, 当同一个流程中第二次调用getSingleton(“a”, true) 就会触发工厂方法中的提前引用方法, 也会触发代理判断, 所以提前引用逻辑包含了aop代理生成逻辑, 即: 提前引用不一定会生成代理, 但是提前生成代理一定需要提前引用

如果可以从缓存中获取到对象, 就不必去完成后续的实例化, 属性填充, 初始化, aop代理, 因为不管这个对象是从哪一级缓存中获取到的, 后续步骤要么已经完成(从一级缓存中获取到的),要么是该这个bean的最初一次getBean()方法的属性填充之后的再去完成初始化, 反正不应该是其他bean触发的getBean()去完成从缓存中获取的bean的后续初始化


添加到半成品池的时机

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   Object singletonObject = this.singletonObjects.get(beanName);
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) {
         singletonObject = this.earlySingletonObjects.get(beanName);
         if (singletonObject == null && allowEarlyReference) {
            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
               singletonObject = singletonFactory.getObject();
               this.earlySingletonObjects.put(beanName, singletonObject); // 添加到半成品池 
               this.singletonFactories.remove(beanName); // 从工厂池中移除
            }
         }
      }
   }
   return singletonObject;
}

带createBean的getSingleton方法

// AbstractBeanFactory#doGetBean("a", A.class)
sharedInstance = getSingleton(beanName, () -> { // ObjectFactory.getObject()
   try {
      return createBean(beanName, mbd, args);
   }
}

2. 实例化

AbstractAutowireCapableBeanFactory#doCreateBean

AbstractAutowireCapableBeanFactory#createBeanInstance: 创建实例


添加单例工厂池

创建实例只有,属性填充之前, 将提前应用的工厂方法放入工厂池中的

if (earlySingletonExposure) {
   addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// **添加单例工厂池**
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); // 注册单例beanName的容器中
        }
    }
}

AbstractAutowireCapableBeanFactory#populateBean: 属性填充

AbstractAutowireCapableBeanFactory#initializeBean:初始化

try {
   populateBean(beanName, mbd, instanceWrapper); // 属性填充, 循环依赖的关键点
   exposedObject = initializeBean(beanName, exposedObject, mbd); // 初始化
}

3. 属性填充

AbstractAutowireCapableBeanFactory#populateBean: 属性填充

注解形式的属性填充

for (BeanPostProcessor bp : getBeanPostProcessors()) {
   if (bp instanceof InstantiationAwareBeanPostProcessor) {
      InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
       // javaconfig配置的属性填充代码
      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;
   }
}

xml形式的属性填充入口

if (pvs != null) {
   applyPropertyValues(beanName, mbd, bw, pvs);// xml配置的属性填充代码
}

4. 初始化

AbstractAutowireCapableBeanFactory#initializeBean:初始化

AbstractAutowireCapableBeanFactory#invokeAwareMethods: Aware接口调用

private void invokeAwareMethods(final String beanName, final Object bean) {
   if (bean instanceof Aware) {
      if (bean instanceof BeanNameAware) {
         ((BeanNameAware) bean).setBeanName(beanName); // beanName
      }
      if (bean instanceof BeanClassLoaderAware) {
         ClassLoader bcl = getBeanClassLoader();
         if (bcl != null) {
            ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); // ClassLoader
         }
      }
      if (bean instanceof BeanFactoryAware) { // beanFactory
         ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
      }
   }
}

BeanPostProcessor#postProcessBeforeInitialization: 调用初始化之前的后置处理器

​ 在任何 bean 初始化回调(如 InitializingBean 的afterPropertiesSet或自定义 init 方法)之前将此BeanPostProcessor应用于给定的新 bean 实例

AbstractAutowireCapableBeanFactory#invokeInitMethods: 初始化方法

InitializingBean 的afterPropertiesSet或自定义 init 方法(@PostConstructor或者xml配置中的init-method)

先调用InitializingBean.afterPropertiesSet再调用自定义的初始化方法

BeanPostProcessor#postProcessAfterInitialization: 调用出初始化之后的后置处理器

​ 在任何 bean 初始化回调(如 InitializingBean 的afterPropertiesSet或自定义 init 方法)之后,将此BeanPostProcessor应用于给定的新 bean 实例

AbstractAutoProxyCreator#postProcessAfterInitialization: 处理aop实现的方法

this.earlyProxyReferences.remove(cacheKey) != bean // 如果已经被提前引用, 就会返回相同的bean实例, 然后不在重复生成代理

5. 注册一次性bean的销毁方法

AbstractBeanFactory#registerDisposableBeanIfNecessary

注册到一次性bean的容器中, 注册destroy方法

public void registerDisposableBean(String beanName, DisposableBean bean) {
	synchronized (this.disposableBeans) {
		this.disposableBeans.put(beanName, bean);
	}
}

添加到单例池的时机

DefaultSingletonBeanRegistry#addSingleton

protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
      this.singletonObjects.put(beanName, singletonObject);
      this.singletonFactories.remove(beanName); // 从工厂池中移除
      this.earlySingletonObjects.remove(beanName); // 从半成品池中移除
      this.registeredSingletons.add(beanName); // 注册单例beanName, Set集合, 因为在反复调用, 所以必须是Set集合
   }
}

此场景是没有bean进入过半成品池中

三. aop代理bean的非循环依赖的bean生命周期的流程

  1. 获取bean
  2. 实例化
  3. 属性填充
  4. 初始化
  5. 注册一次性bean的销毁方法

只有初始化时候调用初始化之后的后置处理器的过程不一样, 其他流程和"普通非循环bean声明中期一样", 初始化之后的后置处理器需要为其生成aop代理, 返回代理, 最后直接放入单例池中

此场景是没有bean进入过半成品池中

四. 普通bean的循环依赖bean生命周期的流程

整体流程和普通bean生命周期也大同小异, 不同点在属性填充会触发其他bean的getBean操作

  1. 获取bean a(getBean(a))

  2. 实例化a

  3. a属性填充

    1. 触发getBean(b)

    2. 实例化b

    3. b属性填充

      触发getBean(a): 此时工厂池命中, 返回普通的bean实例,完成填充

    4. b初始化

    5. b注册一次性bean的销毁方法

  4. a初始化

  5. a注册一次性bean的销毁方法

此场景是普通bean进入过半成品池中

五. aop代理bean的循环依赖bean生命周期的流程

和普通bean循环依赖场景类似, 不同点在, 工厂池中的工厂方法提前生成了aop代理, 初始化之后就不用再次生成代理了

  1. 获取bean a(getBean(a))

  2. 实例化a

  3. a属性填充

    1. 触发getBean(b)

    2. 实例化b

    3. b属性填充

      触发getBean(a): 此时工厂池命中, 返回aop代理的bean实例,完成填充

    4. b初始化

      但是b实例还是在**“初始化之后的后置处理器”**生成aop代理了, 因为b不是发生循环的那一次getBean, 不会命中工厂池

    5. b注册一次性bean的销毁方法

  4. a初始化

    **“初始化之后的后置处理器”**不会再生成aop代理了

  5. a注册一次性bean的销毁方法

此场景是代理bean进入过半成品池中

六. 三级缓存的作用

总结下三级缓存添加移除的时机

获取bean时候: 添加半成品池的时机 (只有出现循环依赖时候, 工厂bean中有工厂方法时候才会触发)

创建实例之后, 填充属性之前: 添加工厂池的时机, 每一个需要实例化的bean都会执行这段逻辑

初始化和一次性bean销毁方法注册完成之后: 添加单例池的时机, bean实例是方法返回的, 所以直接移除半成品池和工厂池

所以我们bean引用会在池子中存在的情况如下

image-20220219223925389

所以我们知道, bean实例的引用一定会进入工厂池, 最终放入单例池, 出现循环依赖才会进入半成品池

三级缓存的作用

单例池作用: 解决获取不完整bean的

半成品池作用: 解决循环依赖和避免aop代理的多次执行

工厂池作用: 创建实例本生时候, 不用关心自己是否有被循环引用, 是否有被代理(考虑是否有没有被代理的前提是循环引用).如果出现循环依赖, 生成代理工作交给出现循环依赖的时候再处理, 这样就能过保证在一个场景下的什么周期的逻辑一致性

​ 在一个bean第一次被getBean时候, 她的执行流程总是这样的

​ 获取bean>实例化bean>bean的属性填充>初始化bean>初始化之后的后置处理器: 如果还没有生成代理, 需要aop的bean,为其生成代理>注册单例bean的销毁方法

​ 另外工厂池中放入的是方法不是bean实例, 所以也必须单独使用一个缓存

举报

相关推荐

0 条评论