spring源碼:bean加載之創建bean-提前曝光bean的Object-Factory

一、介紹

  提前曝光bean的Object-Factory是spring爲了解決bean循環依賴的一種方法。

  • 什麼是循環依賴
    在這裏插入圖片描述
    spring加載一個bean需要兩個步驟:1.創建bean;2.給這個bean填充屬性
    如上圖,加載類A的步驟爲:
  1. 先創建A,然後給A填充屬性的時候,發現A依賴一個類B屬性,所以去加載B;
  2. 創建B,然後給B填充屬性的時候,發現B依賴一個類C屬性,所以去加載C;
  3. 創建C,然後給C填充屬性的時候,發現C依賴一個A屬性,所以又會去加載A。。。

這樣就形成了沒完沒了的循環依賴!

  • 解決辦法:提前曝光bean的Object-Factory
    當創建一個bean之後,不等執行填充屬性這個步驟,就把該bean實例存入到一個Map中(DefaultSingletonBeanRegistry#singletonFactories),創建一個bean時,就先去這個Map中查找有沒有對應的bean實例已經創建了,如果有的話直接就屬性填充完成了。

spring只解決了單例中,setter注入引起的循環依賴問題。原型bean和構造器注入引起的循環依賴問題不能解決。

二、bean加載流程

  1. 獲取用戶傳入name對應的beanName
  2. 嘗試從緩存中獲取bean實例
  3. 緩存中不存在,加載bean實例
    3.1. 檢查循環依賴
    3.2 處理parentBeanFactory
    3.3 處理依賴的bean(dependsOn)
    3.4 三種bean實例的創建
     3.4.1 單例bean的創建
      3.4.1.1 獲取單例bean,getSingleton()方法
      3.4.1.2 準備創建bean,createBean()方法
      3.4.1.3 創建bean,doCreateBean()方法
       3.4.1.3.1 創建BeanWrapper
       3.4.1.3.2 記錄bean的Object-Factory(本章解析
     3.4.2 原型bean的創建
     3.4.3 根據scope策略創建bean
  4. 從bean實例中獲取真正的對象
  5. 轉換對象類型
  6. 返回對象實例

三、相關類及方法

  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean:創建bean流程
  • org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingletonFactory:提前曝光bean
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference:獲取提前依賴的bean(循環依賴的情況使用)

四、源碼分析

1. 提前曝光單例bean

		// 單例&&允許循環引用&&該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");
			}
			// 把創建實例的ObjectFactory加入單例工廠
			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)) {
				// 創建bean實例的ObjectFactory加入到singletonFactories
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}
  • 創建中的beanName
    保存在DefaultSingletonBeanRegistry#singletonsCurrentlyInCreation中。執行保存bean狀態的代碼邏輯在DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>),創建bean之前會把該bean保存到singletonsCurrentlyInCreation,創建完成之後從singletonsCurrentlyInCreation移除。
  • 提前曝光的bean
    該bean保存在DefaultSingletonBeanRegistry#singletonFactories,用來解決循環依賴。

2. 獲取提前曝光的bean

	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					// 應用SmartInstantiationAwareBeanPostProcessor
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		return exposedObject;
	}

這個方法的入參bean,其實已經是創建好的bean實例了。經過這個方法是爲了給用戶自定義的SmartInstantiationAwareBeanPostProcessor一個機會,來根據自己的需要制定一個需要的bean。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章