spring 循环依赖和生命周期

 本文主要说的是Spring是如何解决bean循环依赖的问题,循环依赖和生命周期交织在一起的。

生命周期图:

 spring 循环依赖和生命周期

 

Spring容器初始化时会读取 我们配置bean的信息。然后再一个一个的创建:

 DefaultListableBeanFactory.class:

     public void preInstantiateSingletons() throws BeansException {
		 //beanNames中包含了Spring中所有待创建bean的名称。
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
		for (String beanName : beanNames) {
			……
		    //这里调用getBean不是为了获取bean,没有接收getBean的返回值。而是为了确保 要创建的bean都已创建
		    //getBean方法先会检测是否已经创建该bean,如果已创建则从缓存中获取,如果没有创建则新建。
		    getBean(beanName);
			……
		}
		 ……
	}

getBean方法: 

public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args){
   //调用doGetBean
   return doGetBean(name, requiredType, args, false);
}


protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) {
   //name可能为别名,这里转换成真实的beanName。
   final String beanName = transformedBeanName(name);
   Object bean;

   // Eagerly check singleton cache for manually registered singletons.
   // 从缓存中获取 bean 实例
   Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null && args == null) {//已经创建了bean实例
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }
   else {//还没有创建了bean实例

      //如果是Prototype的循环依赖,直接报错。
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      // 检查父工厂中是否存在该bean.如果存在从父工厂获取。
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
          ……
      }

      if (!typeCheckOnly) {
        //将beanName放入alreadyCreated集合中,表明该bean已经准备开始创建。
         markBeanAsCreated(beanName);
      }

      try {
         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // 保证当前bean所dependsOn的bean被初始化
         // <bean  name="***" class="***" depends-on="***" ></bean>
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
             ……
         }

         //创建bean实例 Create bean instance.
         if (mbd.isSingleton()) {//单例Singleton
            sharedInstance = getSingleton(beanName, () -> {
               try {
                  return createBean(beanName, mbd, args);
               }
               catch (BeansException ex) {
               }
            });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }
         else if (mbd.isPrototype()) {//Prototype
           ……
         }
         else {
            ……
         }
      }
      catch (BeansException ex) {
      }
   }

   ……
   return (T) bean;
}

在getBean是一个空壳方法,getBean将任务交给了doGetBean去完成。在doGetBean中,在获取bean的过程中,首先判断缓存中是否有该bean,如果有使用缓存中的bean,如果没有再创建。

1、如何从缓存中获取bean?

public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 从 singletonObjects 获取实例,singletonObjects 中的实例都是准备好的 bean 实例,可以直接使用
    Object singletonObject = this.singletonObjects.get(beanName);
    // 判断 beanName 对应的 bean 是否正在创建中
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            // 从 earlySingletonObjects 中获取提前曝光的 bean
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                // 获取相应的 bean 工厂
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    // 提前曝光 bean 实例(raw bean),用于解决循环依赖
                    singletonObject = singletonFactory.getObject();
                    // 将 singletonObject 放入缓存中,并将 singletonFactory 从缓存中移除
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

getSingleton(String) 是一个空壳方法,其主要逻辑在 getSingleton(String, boolean) 中。该方法逻辑比较简单,首先从 singletonObjects 缓存中获取 bean 实例。若未命中,再去 earlySingletonObjects 缓存中获取原始 bean 实例。如果仍未命中,则从 singletonFactory 缓存中获取 ObjectFactory 对象,然后再调用 getObject 方法获取原始 bean 实例的应用,也就是早期引用。获取成功后,将该实例放入 earlySingletonObjects 缓存中,并将 ObjectFactory 对象从 singletonFactories 移除。

2、如何创建bean?

这里只说单例bean的创建,其使用的是 getSingleton(String , ObjectFactory)方法:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    synchronized (this.singletonObjects) {
        ......
        // 调用 getObject 方法创建 bean 实例
        singletonObject = singletonFactory.getObject();
        newSingleton = true;

        if (newSingleton) {
            // 添加 bean 到 singletonObjects 缓存中,并从其他集合中将 bean 相关记录移除
            addSingleton(beanName, singletonObject);
        }
        ......
        // 返回 singletonObject
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
}

protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        // 将 <beanName, singletonObject> 映射存入 singletonObjects 中
        this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));

        // 从其他缓存中移除 beanName 相关映射
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.add(beanName);
    }
}

上面的代码中包含两步操作,第一步操作是调用 getObject 创建 bean 实例,第二步是调用 addSingleton 方法将创建好的 bean 放入缓存中。代码逻辑并不复杂,相信大家都能看懂。那么接下来我们继续往下看,getObject 会调createBean,createBean会调doCreateBean 中。doCreateBean 如下:

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

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		
		if (instanceWrapper == null) {
			// 创建 bean 对象,并将 bean 对象包裹在 BeanWrapper 对象中返回,这里的bean的属性依赖还没有注入。
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		//从BeanWrapper中获取bean
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		

		
		//earlySingletonExposure 用于表示是否”提前暴露“原始对象的引用,用于解决循环依赖。对于单例 bean,该变量一般为 true。
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		//earlySingletonExposure为true时,需要缓存
		if (earlySingletonExposure) {
			//bean 会被封装在ObjectFactory中,可以通过ObjectFactory的getObject获取。
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			//注入bean所依赖的对象,setter方式。
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable 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 " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}
	

 

1、创建bean:

	//创建bean的实例。
	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		……
		//如果指定了有参的构造函数。
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
			//有参构造函数,参数会通过getBean方法从Spring容器中获取。
			return autowireConstructor(beanName, mbd, ctors, args);
		}
		//默认使用无参的构造函数。
		return instantiateBean(beanName, mbd);
	}

createBeanInstance默认会通过无参的构造方法创建bean。

2、将bean缓存

	//bean 会被封装在ObjectFactory中,可以通过ObjectFactory的getObject获取。
	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		synchronized (this.singletonObjects) {
		    //再次确认该bean是否已经创建完成(实例+属性注入)。
			if (!this.singletonObjects.containsKey(beanName)) {//未创建完成,已实例化。
				this.singletonFactories.put(beanName, singletonFactory);//bean会被封装在ObjectFactory中,并放入singletonFactories中。
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}

3、依赖属性注入

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		……
	}

populateBean方法内容比较多,其核心就是A依赖B,那么就通过getBean方法获取B,在设置到A中。

4、初始化bean

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {

        //检测Aware接口并设置相关依赖。
        invokeAwareMethods(beanName, bean);
		
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
           //调用bean 的后置处理器中的 beforeInitialization。
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }

        try {
            //这个包含了InitializingBean.afterPropertiesSet和 init-method的调用
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch () {}

        if (mbd == null || !mbd.isSynthetic()) {
           //调用bean 的后置处理器中的 AfterInitialization
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

 

上一篇:Spring IoC bean 的加载


下一篇:spring 循环依赖的一次 理解