欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring核心容器之Bean創(chuàng)建過程詳解

 更新時間:2023年11月17日 08:41:13   作者:龍三丶  
這篇文章主要介紹了Spring核心容器之Bean創(chuàng)建過程詳解,獲取?Bean?的方法是?getBean,其來自?BeanFactory?繼承的AbstractAutowireCapableBeanFactory?抽象類繼承的AbstractBeanFactory?抽象類中,需要的朋友可以參考下

前言

獲取 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);
	}

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

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

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

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

    /** 
     * 1、單例 Bean 在 Spring 的同一個容器內(nèi)只會被創(chuàng)建一次,后續(xù)再獲取 Bean,直接從單例緩存中獲取
     * 2、這里先從單例 Bean 的緩存容器中,嘗試獲取目標(biāo) Bean 
     * ( getSingleton 方法中存在解決單例 Bean 循環(huán)依賴問題的具體方案,這部分會在后面的章節(jié)詳細討論)
     */ 
	Object sharedInstance = getSingleton(beanName);
	
	// 如果存在目標(biāo) Bean
    if (sharedInstance != null && args == null) {
        if (logger.isDebugEnabled()) {
        
            // 目標(biāo) Bean 是否正在被創(chuàng)建
            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 進行轉(zhuǎn)換,最終得到的才是符合要求的bean實例。
        // 2、有時候存在如 FactoryBean 這種并不是直接返回實例本身,而是返回指定方法返回的實例
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    // 如果不存在目標(biāo) Bean
    else {
    
        // 如果當(dāng)前正在創(chuàng)建原型 Bean,則處于循環(huán)依賴中,且原型 Bean 無法解決循環(huán)依賴,所以拋出異常
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // 如果 beanDefinitionMap 也就是容器中不存在目標(biāo) 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 標(biāo)記為已經(jīng)創(chuàng)建(或?qū)⒁獎?chuàng)建),即將 beanName 加入 alreadyCreated 集合中
            markBeanAsCreated(beanName);
        }

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

            // 獲取目標(biāo) 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);
                    }
                }
            }

            /* 開始創(chuàng)建目標(biāo) bean 實例,根據(jù) bean 的 scope  執(zhí)行不同的創(chuàng)建方式。單例,原型,其他的scope */

            // 這是單例的 bean 創(chuàng)建方式
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // 創(chuàng)建 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 創(chuàng)建方式
            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 的類型轉(zhuǎn)換為 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 實例的緩存容器中,嘗試獲取目標(biāo) Bean ,若存在,則直接執(zhí)行最后一步,將 Bean 的類型轉(zhuǎn)換為 getBean 時指定的 requireType 類型,之后返回
  3. 若不存在,則進入創(chuàng)建 Bean 實例的流程
  4. 如果當(dāng)前正在創(chuàng)建原型 Bean 實例,則處于循環(huán)依賴中,且原型 Bean 無法解決循環(huán)依賴,所以拋出異常
  5. 如果當(dāng)前 BeanFactory 中不存在目標(biāo) BeanDefinition,則從父 BeanFactory 獲取
  6. 獲取目標(biāo) BeanDefinition,如果獲取的 BeanDefinition 是子類 BeanDefinition(如 GenericBeanDefinition),則通過與父級合并,返回目標(biāo) bean 的 RootBeanDefinition
  7. 如果存在依賴的 Bean,則先實例化這些依賴的 Bean
  8. 依據(jù)當(dāng)前 Bean 的作用域,開始實例化 Bean ,單例或原型
  9. 判斷實例化的 Bean 是否是 FactoryBean 類型
  10. 將 Bean 的類型轉(zhuǎn)換為 getBean 時指定的 requireType 類型
  11. 最后返回 Bean 實例

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

2、核心流程

2.1 解析 FactoryBean

關(guān)于 FactoryBean 在上一篇《Spring(七)核心容器 - 鉤子接口》文章中已經(jīng)討論過,F(xiàn)actoryBean 是 Spring 提供的鉤子接口,其屬于一種特殊的 Bean,不同于普通的 Bean,它是用來創(chuàng)建 Bean 實例的,屬于工廠 Bean,不過它和普通的創(chuàng)建不同,它提供了更為靈活的方式,一般用來創(chuàng)建那些創(chuàng)建過程比較復(fù)雜的 Bean。

而 FactoryBean 則是通過 getObjectForBeanlnstance 進行解析。getObjectForBeanlnstance 是個高頻率使用的方法,無論是從緩存中獲得 bean 還是根據(jù)不同的 scope 策略加載bean??傊?,我們得到 bean 的實例后要做的第一步就是調(diào)用這個方法來檢測一下正確性,其實就是用于檢測當(dāng)前 bean 是否是 FactoryBean 類型的 bean ,如果是,那么需要調(diào)用該 bean 對應(yīng)的 FactoryBean 實例中的 getObject() 方法返回值作為真正返回的對象。

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

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

	// 如果 beanName 以“&”為前綴,但對應(yīng)的 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 創(chuàng)建的對象
	Object object = null;
	if (mbd == null) {
		object = getCachedObjectForFactoryBean(beanName);
	}
	if (object == null) {
		// 到這里已確定 beanInstance 一定是 FactoryBean 類型,所以進行強轉(zhuǎn)
		FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
		// 獲取 bean 對應(yīng)的 BeanDefinition
		if (mbd == null && containsBeanDefinition(beanName)) {
			mbd = getMergedLocalBeanDefinition(beanName);
		}
		// 當(dāng)前 bean 是否是用戶定義的,而不是應(yīng)用程序自己定義的
		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()) {
		    // 嘗試從緩存中獲取,緩存中存儲的是已經(jīng)通過 FactoryBean 創(chuàng)建的 bean 
			Object object = this.factoryBeanObjectCache.get(beanName);
			if (object == null) {
			
			    // 通過 FactoryBean 創(chuàng)建真正的 bean 
				object = doGetObjectFromFactoryBean(factory, beanName);
				
				// 這里大概是 在執(zhí)行上一步 doGetObjectFromFactoryBean 方法過程中,該 bean 已被其它線程創(chuàng)建并緩存了起來
				Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
				if (alreadyThere != null) {
					object = alreadyThere;
				}
				else { // 如果沒有
					if (shouldPostProcess) { // Bean 是否要進行后置處理
						...
						
						try {
						    // 執(zhí)行后置處理器(關(guān)于后置處理器已在上篇文章討論過)
							object = postProcessObjectFromFactoryBean(object, beanName);
						}
						
						// catch ...
					}
					...
				}
			}
			return object;
		}
	}
	else { // 如果不是單例 bean 
	    // 通過 FactoryBean 創(chuàng)建真正的 bean 
		Object object = doGetObjectFromFactoryBean(factory, beanName);
		if (shouldPostProcess) {
			try {
			    // 執(zhí)行后置處理器
				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 {
		    // 調(diào)用 FactoryBean 的 getObject 方法,返回真正的 bean
			object = factory.getObject();
		}
	}
	// try...catch...
	...
	return object;
}

可以看到,最后調(diào)用的就是 FactoryBean.getObject 方法

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

當(dāng)某個 bean 的實例化過程比較復(fù)雜時,可通過實現(xiàn) FactoryBean 接口,然后在重寫的 getObject 方法中定義實例化 bean 的邏輯,以后獲取該 bean 時,會通過調(diào)用 getObject 方法進行返回。值得注意的是 mybatis 底層就是通過 FactoryBean 來實現(xiàn)。

2.2 從 createBean 開始

接著進入創(chuàng)建 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;

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

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

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

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

繼續(xù)進入 doCreateBean 方法中:

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

	// BeanWrapper 包裝了 bean 對象,緩存了 bean 的內(nèi)省結(jié)果,并可以訪問 bean 的屬性、設(shè)置 bean 的屬性值
	BeanWrapper instanceWrapper = null;
	// 如果是單例,嘗試獲取對應(yīng)的 BeanWrapper
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
	    /*
         * 說明對應(yīng)的bean還沒有創(chuàng)建,用對應(yīng)的策略(工廠方法、構(gòu)造函數(shù))創(chuàng)建 bean 實例,以及簡單初始化
         *
         * 將 beanDefinition 轉(zhuǎn)成 BeanWrapper,大致流程如下:
         * 1. 如果存在工廠方法,則使用工廠方法初始化
         * 2. 否則,如果存在多個構(gòu)造函數(shù),則根據(jù)參數(shù)確定構(gòu)造函數(shù),并利用構(gòu)造函數(shù)初始化
         * 3. 否則,使用默認構(gòu)造函數(shù)初始化
         */
		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;
	}

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

	//  檢查是否需要提前曝光,避免循環(huán)依賴(循環(huán)依賴問題會在后面詳細討論)
	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);
		// 執(zhí)行一系列的初始化方法
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
	// catch...

    // 再次檢查是否循環(huán)依賴
	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. 如果不存在對應(yīng)的 Wrapper,則說明 bean 未被實例化,創(chuàng)建 bean 實例
  3. 執(zhí)行 MergedBeanDefinitionPostProcessor 后置處理器
  4. 檢查是否需要提前曝光,避免循環(huán)依賴
  5. 屬性填充,將所有屬性填充至bean 的實例中。
  6. 執(zhí)行一系列的初始化方法(回調(diào)鉤子接口)
  7. 再次檢查是否存在循環(huán)依賴
  8. 注冊 DisposableBean

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

2.2.1 創(chuàng)建 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());
	}

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

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

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

	// 使用默認的構(gòu)造函數(shù)
	return instantiateBean(beanName, mbd);
}

以上主要分為:

  • 使用工廠方法進行實例化
  • 通過構(gòu)造函數(shù)實例化

不管是通過工廠方法還是構(gòu)造方法來實例化對象,到這里得到的也僅僅是一個 bean 的最初實例,還不是我們最終期望的 bean,因為后面還需要對 bean 實例進行初始化處理,注入相應(yīng)的屬性值等。

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

屬性注入通過 populateBean 方法實現(xiàn):

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // 判斷實例化的 bean 是否為空
	if (bw == null) {
	    // 返回是否有為此 bean 定義的屬性值,如果有,則拋異常,提示 “無法將屬性值應(yīng)用于空實例”
		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;
		}
	}

	// 在設(shè)置屬性之前,先執(zhí)行 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;
				}
			}
		}
	}
    // 當(dāng)使用了 InstantiationAwareBeanPostProcessors 后置處理器注入屬性,則結(jié)束屬性注入流程,直接返回
	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);

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

		// 根據(jù)類型自動注入
		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);
		// 在屬性注入前執(zhí)行 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) {
	    // 執(zhí)行屬性注入
		applyPropertyValues(beanName, mbd, bw, pvs);
	}
}

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

接著進入 initializeBean 方法,在該方法中會回調(diào)許多在 Bean 初始化階段執(zhí)行的方法。

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

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

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

	try {
	    // 回調(diào) 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()) {
	    // 回調(diào) BeanPostProcessor 后置處理器的 postProcessAfterInitialization 方法
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

可以看到,在 Bean 的初始化階段,分別回調(diào)了 Aware 系列接口、BeanPostProcessor 后置處理器、InitializingBean 。這三個接口都屬于 Spring 的鉤子接口,是 Spring 開放出來的擴展接口,可以影響 Bean 的生命周期。

Bean 的初始化階段

1、回調(diào) Aware 系列接口

private void invokeAwareMethods(final String beanName, final Object bean) {   
    
	if (bean instanceof Aware) {
	    // 如果當(dāng)前 Bean 繼承了 BeanNameAware 接口,則回調(diào)接口中的 setBeanName 方法,并傳遞 beanName 參數(shù)
		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);
		}
	}
}

這里被回調(diào)的 Aware 接口有三個,分別是 BeanNameAware 、BeanClassLoaderAware、BeanFactoryAware。

2、回調(diào) BeanPostProcessor 后置處理器的 postProcessBeforeInitialization 方法

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

	Object result = existingBean;
	
	// getBeanPostProcessors 方法獲取所有的 BeanPostProcessor 后置處理器的實現(xiàn),并循環(huán)執(zhí)行 postProcessBeforeInitialization 方法,參數(shù)是當(dāng)前 Bean 以及 beanName 。
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

其中有一個后置處理器的實現(xiàn) ApplicationContextAwareProcessor ,其用來對剩余的 Aware 接口進行回調(diào):

@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、回調(diào) InitializingBean 的 afterPropertiesSet 方法

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {
	//..
			((InitializingBean) bean).afterPropertiesSet();
	//..
}

4、回調(diào) BeanPostProcessor 后置處理器的 postProcessAfterInitialization 方法

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {
	Object result = existingBean;
	// getBeanPostProcessors 方法獲取所有的 BeanPostProcessor 后置處理器的實現(xiàn),并循環(huán)執(zhí)行 postProcessAfterInitialization 方法,參數(shù)是當(dāng)前 Bean 以及 beanName 。
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

到這里,創(chuàng)建 Bean 的核心流程就討論結(jié)束,可歸納為:

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

到此這篇關(guān)于Spring核心容器之Bean創(chuàng)建過程詳解的文章就介紹到這了,更多相關(guān)Spring的Bean創(chuàng)建過程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java驗證碼生成的基本流程

    java驗證碼生成的基本流程

    這篇文章主要介紹了java驗證碼生成的基本流程,需要的朋友可以參考下
    2015-11-11
  • J2ME 程序開發(fā)注意要點

    J2ME 程序開發(fā)注意要點

    講Java基礎(chǔ)的書籍中都是以J2SE來講基礎(chǔ),這就給學(xué)習(xí)造成了一些不必要的麻煩,下面將J2ME中用到的和不需要的Java基礎(chǔ)知識做一個簡單的說明
    2016-07-07
  • IDEA 2019.1.3 激活碼大全

    IDEA 2019.1.3 激活碼大全

    本文是小編給大家收藏整理的IDEA 2019.1.3 激活碼大全,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧
    2019-10-10
  • Java利用AlphaComposite類合并圖像

    Java利用AlphaComposite類合并圖像

    這篇文章主要介紹了Java利用AlphaComposite類合并圖像,幫助大家更好的利用Java處理圖像,感興趣的朋友可以了解下
    2020-10-10
  • JPA save()方法將字段更新為null的解決方案

    JPA save()方法將字段更新為null的解決方案

    這篇文章主要介紹了JPA save()方法將字段更新為null的解決方案,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-01-01
  • Java Collections.sort()排序代碼案例

    Java Collections.sort()排序代碼案例

    這篇文章主要介紹了Java Collections.sort()排序代碼案例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • Java實現(xiàn)ECDSA簽名算法

    Java實現(xiàn)ECDSA簽名算法

    這篇文章主要介紹了Java實現(xiàn)ECDSA簽名算法,幫助大家更好得利用Java實現(xiàn)機器學(xué)習(xí)算法,感興趣的朋友可以了解下
    2020-10-10
  • Java遞歸讀取文件例子_動力節(jié)點Java學(xué)院整理

    Java遞歸讀取文件例子_動力節(jié)點Java學(xué)院整理

    本文通過一段示例代碼給大家介紹了java遞歸讀取文件的方法,代碼簡單易懂,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2017-05-05
  • java實現(xiàn)微信公眾號掃一掃

    java實現(xiàn)微信公眾號掃一掃

    這篇文章主要為大家詳細介紹了java實現(xiàn)微信公眾號掃一掃,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • Java基本知識點之變量和數(shù)據(jù)類型

    Java基本知識點之變量和數(shù)據(jù)類型

    這篇文章主要給大家介紹了關(guān)于Java基本知識點之變量和數(shù)據(jù)類型的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04

最新評論