Spring(八)核心容器 - Bean 創建過程

Spring 版本 5.0.7.RELEASE

獲取 Bean 的方法是 getBean,其來自 BeanFactory 繼承的 AbstractAutowireCapableBeanFactory 抽象類繼承的 AbstractBeanFactory 抽象類中。

1、整體流程

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    
    ...
    // 通過 beanName 獲取 Bean 實例
    @Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

    // 檢索所需的 bean 類型
	@Override
	public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
		return doGetBean(name, requiredType, null, false);
	}

    // 使用顯式參數創建 Bean 實例時要使用的參數
	@Override
	public Object getBean(String name, Object... args) throws BeansException {
		return doGetBean(name, null, args, false);
	}
	
    ...
}

getBean 有多個重載方法,可分爲通過 Bean 名稱或通過 Class 獲取 Bean 對象,這些重載方法底層都是調用 doGetBean 方法。

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    /**
	 * 1、如果獲取的 Bean 類型是 FactoryBean,則參數 name 會以“&”爲前綴。這裏會去掉該修飾符,並返回.
	 * 2、如果是手動註冊的別名,則將其解析爲規範的名稱
	 */
	final String beanName = transformedBeanName(name);
	Object bean;

    /** 
     * 1、單例 Bean 在 Spring 的同一個容器內只會被創建一次,後續再獲取 Bean,直接從單例緩存中獲取
     * 2、這裏先從單例 Bean 的緩存容器中,嘗試獲取目標 Bean 
     * ( getSingleton 方法中存在解決單例 Bean 循環依賴問題的具體方案,這部分會在後面的章節詳細討論)
     */ 
	Object sharedInstance = getSingleton(beanName);
	
	// 如果存在目標 Bean
    if (sharedInstance != null && args == null) {
        if (logger.isDebugEnabled()) {
        
            // 目標 Bean 是否正在被創建
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                        "' that is not fully initialized yet - a consequence of a circular reference");
            }
            else {
                logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }

        // 1、不論是單例還是原型的實例對象,最終都要通過 getObjectForBeanInstance 進行轉換,最終得到的纔是符合要求的bean實例。
        // 2、有時候存在如 FactoryBean 這種並不是直接返回實例本身,而是返回指定方法返回的實例
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    // 如果不存在目標 Bean
    else {
    
        // 如果當前正在創建原型 Bean,則處於循環依賴中,且原型 Bean 無法解決循環依賴,所以拋出異常
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // 如果 beanDefinitionMap 也就是容器中不存在目標 Bean,則嘗試從父級 beanFactory 中獲取
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // 獲取真正 beanName。如果獲取的 Bean 類型是 FactoryBean,則去掉 beanName 的修飾符“&”
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
                // 遞歸到 BeanFactory 中尋找
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
        }

        if (!typeCheckOnly) {
            // 將指定的 bean 標記爲已經創建(或將要創建),即將 beanName 加入 alreadyCreated 集合中
            markBeanAsCreated(beanName);
        }

        try {
            // 通過 beanName 獲取對應的 BeanDefinition,如果獲取 BeanDefinition 是子類 BeanDefinition,
            // 則通過與父級合併,返回目標 bean 的 RootBeanDefinition
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // 檢查bean是否是抽象的,如果是則拋出異常
            checkMergedBeanDefinition(mbd, beanName, args);

            // 獲取目標 bean 所依賴的其它 bean 名稱
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                // 若存在依賴則需要遞歸實例化依賴的 bean
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    registerDependentBean(dep, beanName);
                    try {
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            /* 開始創建目標 bean 實例,根據 bean 的 scope  執行不同的創建方式。單例,原型,其他的scope */

            // 這是單例的 bean 創建方式
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // 創建 Bean 的核心方法
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {
                        // Explicitly remove instance from singleton cache: It might have been put there
                        // eagerly by the creation process, to allow for circular reference resolution.
                        // Also remove any beans that received a temporary reference to the bean.
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            // prototype 類型的 bean 創建方式
            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            // 其它類型
            else {
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, () -> {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName,
                            "Scope '" + scopeName + "' is not active for the current thread; consider " +
                            "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                            ex);
                }
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // 將 Bean 的類型轉換爲 getBean 時指定的 requireType 類型
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
        }
        catch (TypeMismatchException ex) {
            if (logger.isDebugEnabled()) {
                logger.debug("Failed to convert bean '" + name + "' to required type '" +
                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}

整個方法的過程可以概括爲:

  1. 解析 beanName
  2. 從單例 Bean 實例的緩存容器中,嘗試獲取目標 Bean ,若存在,則直接執行最後一步,將 Bean 的類型轉換爲 getBean 時指定的 requireType 類型,之後返回
  3. 若不存在,則進入創建 Bean 實例的流程
  4. 如果當前正在創建原型 Bean 實例,則處於循環依賴中,且原型 Bean 無法解決循環依賴,所以拋出異常
  5. 如果當前 BeanFactory 中不存在目標 BeanDefinition,則從父 BeanFactory 獲取
  6. 獲取目標 BeanDefinition,如果獲取的 BeanDefinition 是子類 BeanDefinition(如 GenericBeanDefinition),則通過與父級合併,返回目標 bean 的 RootBeanDefinition
  7. 如果存在依賴的 Bean,則先實例化這些依賴的 Bean
  8. 依據當前 Bean 的作用域,開始實例化 Bean ,單例或原型
  9. 判斷實例化的 Bean 是否是 FactoryBean 類型
  10. 將 Bean 的類型轉換爲 getBean 時指定的 requireType 類型
  11. 最後返回 Bean 實例

以上就是 getBean 方法的大致流程,其中有兩個頻繁出現且非常重要的方法,一個是處理 FactoryBean 的 getObjectForBeanInstance方法,另一個是創建 Bean 的核心實現 createBean 方法。

2、核心流程

2.1 解析 FactoryBean

關於 FactoryBean 在上一篇《Spring(七)核心容器 - 鉤子接口》文章中已經討論過,FactoryBean 是 Spring 提供的鉤子接口,其屬於一種特殊的 Bean,不同於普通的 Bean,它是用來創建 Bean 實例的,屬於工廠 Bean,不過它和普通的創建不同,它提供了更爲靈活的方式,一般用來創建那些創建過程比較複雜的 Bean。

而 FactoryBean 則是通過 getObjectForBeanlnstance 進行解析。getObjectForBeanlnstance 是個高頻率使用的方法,無論是從緩存中獲得 bean 還是根據不同的 scope 策略加載bean。總之,我們得到 bean 的實例後要做的第一步就是調用這個方法來檢測一下正確性,其實就是用於檢測當前 bean 是否是 FactoryBean 類型的 bean ,如果是,那麼需要調用該 bean 對應的 FactoryBean 實例中的 getObject() 方法返回值作爲真正返回的對象。

所以,當我們 getBean 的時候,有兩種可能,一種是返回普通的 Bean,另一種是返回通過 getObjectForBeanInstance 方法解析 FactoryBean 返回的 Bean。

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

	// 如果 beanName 以“&”爲前綴,但對應的 bean 不是 FactoryBean 類型,則拋異常
	if (BeanFactoryUtils.isFactoryDereference(name)) {
		if (beanInstance instanceof NullBean) {
			return beanInstance;
		}
		if (!(beanInstance instanceof FactoryBean)) {
			throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
		}
	}

	// 校驗已獲取的 bean 
	// 1、如果該 bean 不是 FactoryBean 類型,直接返回
	// 2、如果是 FactoryBean 類型,且 beanName 以“&”爲前綴,說明想獲取的是 FactoryBean ,也是直接返回
	if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
		return beanInstance;
	}

    // 從緩存中嘗試獲取 FactoryBean 創建的對象
	Object object = null;
	if (mbd == null) {
		object = getCachedObjectForFactoryBean(beanName);
	}
	if (object == null) {
		// 到這裏已確定 beanInstance 一定是 FactoryBean 類型,所以進行強轉
		FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
		// 獲取 bean 對應的 BeanDefinition
		if (mbd == null && containsBeanDefinition(beanName)) {
			mbd = getMergedLocalBeanDefinition(beanName);
		}
		// 當前 bean 是否是用戶定義的,而不是應用程序自己定義的
		boolean synthetic = (mbd != null && mbd.isSynthetic());
		
		// 解析 FactoryBean 的核心方法
		object = getObjectFromFactoryBean(factory, beanName, !synthetic);
	}
	return object;
}

這個方法很簡單,大多是些輔助代碼以及一些功能性的判斷,真正的核心代碼在 getObjectFromFactoryBean 方法中。

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    // 如果是單例 bean 
	if (factory.isSingleton() && containsSingleton(beanName)) {
		synchronized (getSingletonMutex()) {
		    // 嘗試從緩存中獲取,緩存中存儲的是已經通過 FactoryBean 創建的 bean 
			Object object = this.factoryBeanObjectCache.get(beanName);
			if (object == null) {
			
			    // 通過 FactoryBean 創建真正的 bean 
				object = doGetObjectFromFactoryBean(factory, beanName);
				
				// 這裏大概是 在執行上一步 doGetObjectFromFactoryBean 方法過程中,該 bean 已被其它線程創建並緩存了起來
				Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
				if (alreadyThere != null) {
					object = alreadyThere;
				}
				else { // 如果沒有
					if (shouldPostProcess) { // Bean 是否要進行後置處理
						...
						
						try {
						    // 執行後置處理器(關於後置處理器已在上篇文章討論過)
							object = postProcessObjectFromFactoryBean(object, beanName);
						}
						
						// catch ...
					}
					...
				}
			}
			return object;
		}
	}
	else { // 如果不是單例 bean 
	    // 通過 FactoryBean 創建真正的 bean 
		Object object = doGetObjectFromFactoryBean(factory, beanName);
		if (shouldPostProcess) {
			try {
			    // 執行後置處理器
				object = postProcessObjectFromFactoryBean(object, beanName);
			}
			// catch ...
		}
		return object;
	}
}

接着進入該方法中更爲核心的 doGetObjectFromFactoryBean 方法:

private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
			throws BeanCreationException {

	Object object;
	try {
		// try...catch...
		
		else {
		    // 調用 FactoryBean 的 getObject 方法,返回真正的 bean
			object = factory.getObject();
		}
	}
	
	// try...catch...

	...
	
	return object;
}

可以看到,最後調用的就是 FactoryBean.getObject 方法

public interface FactoryBean<T> {
	@Nullable
	T getObject() throws Exception;
}

當某個 bean 的實例化過程比較複雜時,可通過實現 FactoryBean 接口,然後在重寫的 getObject 方法中定義實例化 bean 的邏輯,以後獲取該 bean 時,會通過調用 getObject 方法進行返回。值得注意的是 mybatis 底層就是通過 FactoryBean 來實現。

2.2 從 createBean 開始

接着進入創建 Bean 的下一步 createBean 方法:

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

	if (logger.isDebugEnabled()) {
		logger.debug("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;

	// 根據設置的 class 屬性或 className 來解析得到 Class 引用
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	// 對 override 屬性進行標記和驗證,本質上是處理 lookup-method 和 replaced-method 標籤
	try {
		mbdToUse.prepareMethodOverrides();
	}
	// catch...

	try {
		// 執行 BeanPostProcessors 後置處理器,如果有 bean 返回,則不執行接下來創建 bean 的操作,直接返回該 bean 
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	}
	// catch...

	try {
	    // 創建 Bean 的核心方法
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	// catch...
}

繼續進入 doCreateBean 方法中:

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

	// BeanWrapper 包裝了 bean 對象,緩存了 bean 的內省結果,並可以訪問 bean 的屬性、設置 bean 的屬性值
	BeanWrapper instanceWrapper = null;
	// 如果是單例,嘗試獲取對應的 BeanWrapper
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
	    /*
         * 說明對應的bean還沒有創建,用對應的策略(工廠方法、構造函數)創建 bean 實例,以及簡單初始化
         *
         * 將 beanDefinition 轉成 BeanWrapper,大致流程如下:
         * 1. 如果存在工廠方法,則使用工廠方法初始化
         * 2. 否則,如果存在多個構造函數,則根據參數確定構造函數,並利用構造函數初始化
         * 3. 否則,使用默認構造函數初始化
         */
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	// 從 BeanWrapper 中獲取包裝的 bean 實例
	final Object bean = instanceWrapper.getWrappedInstance();
	// 從 BeanWrapper 獲取包裝 bean 的 class 引用
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}

	// 執行 MergedBeanDefinitionPostProcessor 後置處理器。
	//(這裏涉及一個極其重要的後置處理器實現 AutowiredAnnotationBeanPostProcessor,其主要用來處理 @Autowired 註解,這部分會在後面詳細討論)
	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			try {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			}
			// catch...
			mbd.postProcessed = true;
		}
	}

	//  檢查是否需要提前曝光,避免循環依賴(循環依賴問題會在後面詳細討論)
	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");
		}
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}

	// 開始初始化 bean 
	Object exposedObject = bean;
	try {
	    // 對 bean 進行填充,將各個屬性值注入,如果存在依賴的 bean 則進行遞歸初始化
		populateBean(beanName, mbd, instanceWrapper);
		// 執行一系列的初始化方法
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
	// catch...

    // 再次檢查是否循環依賴
	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 
				}
			}
		}
	}

	// 註冊DisposableBean
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	// catch...

	return exposedObject;
}

該方法整體流程如下:

  1. 如果是單例,嘗試從緩存中獲取 bean 的包裝器 BeanWrapper,並清除緩存
  2. 如果不存在對應的 Wrapper,則說明 bean 未被實例化,創建 bean 實例
  3. 執行 MergedBeanDefinitionPostProcessor 後置處理器
  4. 檢查是否需要提前曝光,避免循環依賴
  5. 屬性填充,將所有屬性填充至bean 的實例中。
  6. 執行一系列的初始化方法(回調鉤子接口)
  7. 再次檢查是否存在循環依賴
  8. 註冊 DisposableBean

該過程中有幾個需要重點介紹的方法,分別是創建 Bean 實例的 createBeaninstance 方法、注入 Bean 屬性的 populateBean 方法以及執行 Bean 初始化方法的 initializeBean 方法。

2.2.1 創建 Bean 實例

從 createBeaninstance 開始:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
	Class<?> beanClass = resolveBeanClass(mbd, beanName);
	if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
				"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
	}

    // 如果有用於創建 bean 實例的回調方法
	Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
	if (instanceSupplier != null) {
		return obtainFromSupplier(instanceSupplier, beanName);
	}
    
    // 如果工廠方法不爲空,則使用工廠方法進行實例化
	if (mbd.getFactoryMethodName() != null)  {
		return instantiateUsingFactoryMethod(beanName, mbd, args);
	}

	// 利用構造函數進行實例化,解析並確定目標構造函數
	boolean resolved = false;
	boolean autowireNecessary = false;
	if (args == null) {
		synchronized (mbd.constructorArgumentLock) {
		    // 一個類可能有多個構造函數,需要根據參數來確定具體的構造函數
			if (mbd.resolvedConstructorOrFactoryMethod != null) {
				resolved = true;
				autowireNecessary = mbd.constructorArgumentsResolved;
			}
		}
	}
	
	// 如果已經解析過,則使用已經確定的構造方法
	if (resolved) {
		if (autowireNecessary) {
		    // 依據構造函數注入
			return autowireConstructor(beanName, mbd, null, null);
		}
		else {
		    // 使用默認構造函數構造
			return instantiateBean(beanName, mbd);
		}
	}

	// 根據參數確定構造函數
	Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	if (ctors != null ||
			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
		return autowireConstructor(beanName, mbd, ctors, args);
	}

	// 使用默認的構造函數
	return instantiateBean(beanName, mbd);
}

以上主要分爲:

  1. 使用工廠方法進行實例化
  2. 通過構造函數實例化

不管是通過工廠方法還是構造方法來實例化對象,到這裏得到的也僅僅是一個 bean 的最初實例,還不是我們最終期望的 bean,因爲後面還需要對 bean 實例進行初始化處理,注入相應的屬性值等。

2.2.2 初始化 Bean 實例 - 屬性注入

屬性注入通過 populateBean 方法實現:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // 判斷實例化的 bean 是否爲空
	if (bw == null) {
	    // 返回是否有爲此 bean 定義的屬性值,如果有,則拋異常,提示 “無法將屬性值應用於空實例”
		if (mbd.hasPropertyValues()) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
		}
		// 沒有,則跳過屬性填充階段以獲取空實例
		else {
			// Skip property population phase for null instance.
			return;
		}
	}

	// 在設置屬性之前,先執行 InstantiationAwareBeanPostProcessors 後置處理器,這些後置處理器可以用其它方式注入屬性,如字段注入。
	boolean continueWithPropertyPopulation = true;
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					continueWithPropertyPopulation = false;
					break;
				}
			}
		}
	}
    // 當使用了 InstantiationAwareBeanPostProcessors 後置處理器注入屬性,則結束屬性注入流程,直接返回
	if (!continueWithPropertyPopulation) {
		return;
	}

    // 獲取 bean 實例的屬性值集合
	PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

	if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

		// 根據名稱自動注入
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
			autowireByName(beanName, mbd, bw, newPvs);
		}

		// 根據類型自動注入
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			autowireByType(beanName, mbd, bw, newPvs);
		}

		pvs = newPvs;
	}

    // 返回此工廠是否擁有 InstantiationAwareBeanPostProcessor
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
	// 是否進行依賴檢查
	boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

	if (hasInstAwareBpps || needsDepCheck) {
		if (pvs == null) {
			pvs = mbd.getPropertyValues();
		}
		PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
		// 在屬性注入前執行 InstantiationAwareBeanPostProcessor 後置處理器
		if (hasInstAwareBpps) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvs == null) {
						return;
					}
				}
			}
		}
		// 進行依賴檢查
		if (needsDepCheck) {
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}
	}

	if (pvs != null) {
	    // 執行屬性注入
		applyPropertyValues(beanName, mbd, bw, pvs);
	}
}

2.2.3 初始化 Bean 實例 - 執行初始化方法(回調鉤子接口)

接着進入 initializeBean 方法,在該方法中會回調許多在 Bean 初始化階段執行的方法。

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

    // 回調 Aware 系列接口
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
		invokeAwareMethods(beanName, bean);
	}

    // 回調 BeanPostProcessor 後置處理器的 postProcessBeforeInitialization 方法
	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
	    // 回調 InitializingBean 的 afterPropertiesSet 方法
		invokeInitMethods(beanName, wrappedBean, mbd);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				(mbd != null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}
	if (mbd == null || !mbd.isSynthetic()) {
	    // 回調 BeanPostProcessor 後置處理器的 postProcessAfterInitialization 方法
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

可以看到,在 Bean 的初始化階段,分別回調了 Aware 系列接口、BeanPostProcessor 後置處理器、InitializingBean 。這三個接口都屬於 Spring 的鉤子接口,是 Spring 開放出來的擴展接口,可以影響 Bean 的生命週期。關於鉤子接口在上一篇的《Spring(七)核心容器 - 鉤子接口》文章已詳細討論,感興趣的同學可自行翻閱。

1、回調 Aware 系列接口

private void invokeAwareMethods(final String beanName, final Object bean) {   
    
	if (bean instanceof Aware) {
	    // 如果當前 Bean 繼承了 BeanNameAware 接口,則回調接口中的 setBeanName 方法,並傳遞 beanName 參數
		if (bean instanceof BeanNameAware) {
			((BeanNameAware) bean).setBeanName(beanName);
		}
		
		// 這個 BeanClassLoaderAware 接口傳遞的是 ClassLoader
		if (bean instanceof BeanClassLoaderAware) {
			ClassLoader bcl = getBeanClassLoader();
			if (bcl != null) {
				((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
			}
		}
		
		// 這個 BeanFactoryAware 接口傳遞的是 AbstractAutowireCapableBeanFactory
		if (bean instanceof BeanFactoryAware) {
			((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
		}
	}
}

這裏被回調的 Aware 接口有三個,分別是 BeanNameAware 、BeanClassLoaderAware、BeanFactoryAware。

2、回調 BeanPostProcessor 後置處理器的 postProcessBeforeInitialization 方法

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

	Object result = existingBean;
	
	// getBeanPostProcessors 方法獲取所有的 BeanPostProcessor 後置處理器的實現,並循環執行 postProcessBeforeInitialization 方法,參數是當前 Bean 以及 beanName 。
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

其中有一個後置處理器的實現 ApplicationContextAwareProcessor ,其用來對剩餘的 Aware 接口進行回調:

@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;

	//...
	
		invokeAwareInterfaces(bean);
	//...

	return bean;
}
private void invokeAwareInterfaces(Object bean) {
	if (bean instanceof Aware) {
		if (bean instanceof EnvironmentAware) {
			((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
		}
		if (bean instanceof EmbeddedValueResolverAware) {
			((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
		}
		if (bean instanceof ResourceLoaderAware) {
			((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
		}
		if (bean instanceof ApplicationEventPublisherAware) {
			((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
		}
		if (bean instanceof MessageSourceAware) {
			((MessageSourceAware) bean).setMessageSource(this.applicationContext);
		}
		if (bean instanceof ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		}
	}
}

3、回調 InitializingBean 的 afterPropertiesSet 方法

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

	//..
			((InitializingBean) bean).afterPropertiesSet();
	
	//..
}

4、回調 BeanPostProcessor 後置處理器的 postProcessAfterInitialization 方法

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	
	// getBeanPostProcessors 方法獲取所有的 BeanPostProcessor 後置處理器的實現,並循環執行 postProcessAfterInitialization 方法,參數是當前 Bean 以及 beanName 。
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

到這裏,創建 Bean 的核心流程就討論結束,可歸納爲:

  1. 解析 beanName
  2. 從單例 Bean 實例的緩存容器中,嘗試獲取目標 Bean
  3. 緩存不存在則開始實例化 Bean ,區分單例或原型
  4. 實例化 Bean、初始化 Bean、執行初始化方法及回調鉤子接口
  5. 判斷實例化的 Bean 是否是 FactoryBean 類型







參考《Spring源碼深度解析(第2版)》

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