天天看点

图解spring的bean创建的生命周期

注意:

  • 实例化是使用class实例化和初始化是实例化之后进行的,博主一直把这个搞混了。所以如果使用后置处理器自定义实例化后spring生命周期直接跳过属性填充这个步骤,表明实例化完成
  • spring的aop是属性填充完成之后这一步返回一个代理对象替换原先的bean实现的。
  • 实例化之后,spring会提前暴露当前的bean引用对象到三级缓存里面,这样可以解决依赖循环问题

spring的三级缓存分类如下:

名称 描述
singletonObjects 一级缓存,存放完整的 Bean。
earlySingletonObjects 二级缓存,存放提前暴露的Bean,Bean 是不完整的,未完成属性注入和执行 init 方法。
singletonFactories 三级缓存,存放的是 Bean 工厂,主要是生产 Bean,存放到二级缓存中。
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {   
		    //如果当前一级缓存里面beanName
			if (!this.singletonObjects.containsKey(beanName)) {    
			    //加入三级缓存
				this.singletonFactories.put(beanName, singletonFactory);
				//清除二级缓存
				this.earlySingletonObjects.remove(beanName);
				
				this.registeredSingletons.add(beanName);
			}
		}
	}
           

依赖注入的时候获取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) {
          // Bean 工厂中获取 Bean
          singletonObject = singletonFactory.getObject();
          // 放入到二级缓存中
          this.earlySingletonObjects.put(beanName, singletonObject);
          //清除二级缓存对象
          this.singletonFactories.remove(beanName);
        }
      }
    }
  }
  return singletonObject;
}
           

备注:

  • 一级缓存,这个就是不用重复创建单例对象
  • 二级缓存防止产生多个代理对象,否则一级缓存和三级缓存就够了。假如依赖循环中,后面有多个属性依赖A的Bean,没有二级缓存就会创建多个。
  • 第三级缓存的目的是为了延迟代理对象的创建,因为如果没有依赖循环的话,那么就不需要为其提前创建代理,可以将它延迟到初始化完成之后再创建。

    -如果使用二级缓存实现,如果 Spring 选择二级缓存来解决循环依赖的话,那么就意味着所有 Bean 都需要在实例化完成之后就立马为其创建代理,而 Spring 的设计原则是在 Bean 初始化完成之后才为其创建代理。所以,Spring 选择了三级缓存。但是因为循环依赖的出现,导致了 Spring 不得不提前去创建代理,因为如果不提前创建代理对象,那么注入的就是原始对象,这样就会产生错误。

参考https://www.jb51.net/article/197450.htm