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

超詳細解析Spring Bean的創(chuàng)建過程

 更新時間:2024年05月17日 09:12:47   作者:薛偉同學(xué)  
這篇文章主要揭秘了Spring Bean的創(chuàng)建過程,文中通過代碼示例和圖文結(jié)合的方式解析的超級詳細,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下

Spring Bean 的生命周期

BeanFactory 創(chuàng)建對象

在 BeanFactory 接口中定義了獲取 Bean 實例的方法 getBean。

@Test
public void testDefaultListableBeanFactory() {
    // 創(chuàng)建工廠
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    // 創(chuàng)建 XML 閱讀器,并指定關(guān)聯(lián)的工廠
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
    // 開始解析加載 Bean
    reader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
    System.out.println(factory.getBean("user"));
}

Spring 工廠創(chuàng)建對象的過程其實就是 factory.getBean("user") 對應(yīng)的實現(xiàn),這個創(chuàng)建邏輯可以說是 Spring 中最復(fù)雜的地方,其中會完整的體現(xiàn)上面生命周期的各個步驟,以及對單例對象、多實例對象的處理,接下來我們將深入源碼,解析整個對象的創(chuàng)建過程。

Bean 創(chuàng)建過程

獲取 Bean 的方法是 getBean,其來自 DefaultListableBeanFactory 的父類 AbstractAutowireCapableBeanFactory 的父類 AbstractBeanFactory。有點繞,其實就是 DefaultListableBeanFactory 的爺爺…

【重載】getBean

AbstractBeanFactory#getBean

通過名稱獲取 Bean,這個名稱可以是 ID,也可以是別名。

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    
    @Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

	@Override
	public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
		return doGetBean(name, requiredType, null, false);
	}
    
	@Override
	public Object getBean(String name, Object... args) throws BeansException {
		return doGetBean(name, null, args, false);
	}
	
    ...
}

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

【從緩存拿或者創(chuàng)建】doGetBean

AbstractBeanFactory#doGetBean

// 為了簡潔美觀,這里將源碼中的部分非核心內(nèi)容進行了刪減
protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) {
    
    // 轉(zhuǎn)換名稱,返回 Bean 的 ID
    // 如果是 FactoryBean 類型,則參數(shù) name 會以 & 為前綴。此方法會去掉該修飾符,并返回后面的內(nèi)容
    // 如果傳入的是 Bean 的別名,則會找到 Bean 的 ID 返回
    final String beanName = transformedBeanName(name);
    Object bean;
    
    // 單例 Bean 只會被創(chuàng)建一次,后續(xù)再獲取 Bean,直接從單例緩存中獲?。ü灿腥壘彺妫?
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        // 如果存在緩存的 Bean
        // 獲取 Bean,正常 Bean 直接返回,如果是 FactoryBean 則返回 FactoryBean.getObject()
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    
    else {
        // 檢驗邏輯
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(...);
        }
        
        // 父子容器的處理
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // 當(dāng)父容器不為空并且獲取的 Bean 不在子容器定義時,從父容器遞歸獲取
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                    nameToLookup, requiredType, args, typeCheckOnly);
            } else if (args != null) {
                // 遞歸到父容器中尋找
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            } else if (requiredType != null) {
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            } else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }
        
        if (!typeCheckOnly) {
            // 將 Bean 標(biāo)記為已經(jīng)創(chuàng)建(或?qū)⒁獎?chuàng)建),即將 beanName 加入 alreadyCreated 集合
            markBeanAsCreated(beanName);
        }
        
        try {
            // 獲取合并后的父子 Bean,對應(yīng) <bean id="p" abstract="true"> 和 <bean id="c" parent="p" 的用法
            // 將子標(biāo)簽 bean 的各個屬性合并到父標(biāo)簽,生成 RootBeanDefinition
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);
            
            // 獲取目標(biāo) bean 所依賴的其它 bean 名稱
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(...);
                    }
                    // 若存在依賴則需要遞歸實例化依賴的 bean
                    registerDependentBean(dep, beanName);
                    try {
                        getBean(dep);
                    } // catch...
                }
            }
            
            if (mbd.isSingleton()) {
                // 創(chuàng)建單例 Bean
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // 創(chuàng)建 Bean 的核心方法
                        return createBean(beanName, mbd, args);
                    } // catch...
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            } 
            
            else if (mbd.isPrototype()) {
                // 創(chuàng)建原型 Bean
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                } finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            } 
            
            else {
                // 創(chuàng)建其他作用域的 Bean
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException(...);
                }
                try {
                    Object scopedInstance = scope.get(beanName, () -> {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        } finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                } // catch...
            }
        } // catch...
    }
    // 將 Bean 的類型轉(zhuǎn)換為 getBean 時指定的 requireType 類型
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(...);
            }
            return convertedBean;
        } // catch...
    }
    return (T) bean;
}

簡單概述一下整個過程:

  1. 第一步【轉(zhuǎn)換名稱】:解析轉(zhuǎn)換傳入的獲取 Bean 的名字,可以分為三種情況:
    1. 傳入的直接是 ID,則無須轉(zhuǎn)換
    2. 傳入的是 Bean 的別名,轉(zhuǎn)換成 Bean 的 ID 返回
    3. 傳入的是 FactoryBean 的 & 寫法,,轉(zhuǎn)換成 Bean 的 ID 返回
  2. 第二步【從緩存中獲取】:單例作用域的 Bean 只會創(chuàng)建一次,之后會存儲在 Spring 的緩存中(共計三層)。如果緩存中存在目標(biāo) Bean,則獲取 Bean,正常 Bean 直接返回,如果是 FactoryBean 則 返回 FactoryBean.getObject()。獲取到 Bean 之后跳到第八步【類型轉(zhuǎn)換】。
  3. 第三步【父子容器的處理】:如果沒有從上面的緩存中拿到數(shù)據(jù),說明這次要重新創(chuàng)建 Bean。首先進行父子容器的處理,當(dāng)父容器不為空并且獲取的 Bean 不在當(dāng)前容器定義時,從父容器遞歸獲取。
  4. 第四步【標(biāo)記 Bean 為被創(chuàng)建】:將 Bean 標(biāo)記為已經(jīng)創(chuàng)建(或?qū)⒁獎?chuàng)建),即將 beanName 加入 alreadyCreated 集合。
  5. 第五步【合并父子 Bean】:獲取合并后的父子 Bean,對應(yīng) <bean id="xx" abstract="true"> 和 <bean id="c" parent="xx" 的用法,這個步驟會將子標(biāo)簽 bean 的各個屬性合并到父標(biāo)簽,生成 RootBeanDefinition。
  6. 第六步【處理依賴 Bean】:獲取當(dāng)前 Bean 是否配置依賴的其他的 Bean 的名稱,若存在依賴則需要遞歸實例化依賴的其他 Bean。這個用法現(xiàn)在已經(jīng)很少了,大家可以忽略。
  7. 第七步【根據(jù)作用域創(chuàng)建 Bean】:根據(jù)作用域可分為三類:單例(singleton)、原型(prototype)和其他,對應(yīng)的 if 的三個分支,最后都會調(diào)用 createBean 創(chuàng)建 Bean。
  8. 第八步【類型轉(zhuǎn)換】:如果獲取 Bean 的時候傳入了期望轉(zhuǎn)換的類型 Class,那么這一步就會進行類型轉(zhuǎn)換,之后就將創(chuàng)建的 Bean 返回給調(diào)用者了。

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

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

【BeanFactory處理】getObjectForBeanInstance

AbstractBeanFactory#getObjectForBeanInstance

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

	// 如果 beanName 以 & 為前綴,但對應(yīng)的 Bean 不是 FactoryBean 類型,則拋異常
	if (BeanFactoryUtils.isFactoryDereference(name)) {
		if (beanInstance instanceof NullBean) {
			return beanInstance;
		}
		if (!(beanInstance instanceof FactoryBean)) {
			throw new BeanIsNotAFactoryException(...);
		}
	}

	// 校驗已獲取的 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 方法中。

【BeanFactory處理】getObjectFromFactoryBean

AbstractBeanFactory#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,其實就是調(diào)用了 factory.getObject() 方法
				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í)行后置處理器
							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;
	}
}

【創(chuàng)建Bean的入口】createBean

AbstractAutowireCapableBeanFactory#createBean

接著進入創(chuàng)建 Bean 的下一步 createBean 方法:

這個 createBean 方法是定義在 AbstractBeanFactory 中的抽象方法,最終的實現(xiàn)是交給了 AbstractAutowireCapableBeanFactory 類實現(xiàn),所以接下來我們看看 AbstractAutowireCapableBeanFactory 這個類。

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) {

	RootBeanDefinition mbdToUse = mbd;

	// 根據(jù)設(shè)置的 class 屬性或 className 來解析得到 Class 引用賦值給 RootBeanDefinition
	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 {
	    // 最后會執(zhí)行到這里,這是創(chuàng)建 Bean 的核心方法
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		return beanInstance;
	} // catch...
}

【創(chuàng)建Bean的主邏輯】doCreateBean

AbstractAutowireCapableBeanFactory#doCreateBean

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

	BeanWrapper instanceWrapper = null;
	// 如果是單例,嘗試獲取對應(yīng)的 BeanWrapper
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
        // 這里是一個關(guān)鍵點,使用對應(yīng)的策略(工廠方法、構(gòu)造函數(shù))創(chuàng)建 Bean 實例,以及簡單初始化
        // BeanWrapper 包裝了 Bean 對象,并封裝類型轉(zhuǎn)換器
		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 后置處理器。
	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) {
		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 方法。

【創(chuàng)建Bean的核心邏輯】createBeaninstance

AbstractAutowireCapableBeanFactory#createBeaninstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
    
	Class<?> beanClass = resolveBeanClass(mbd, beanName);
	if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
		throw new BeanCreationException(...);
	}

    // 如果有用于創(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)的屬性值等。

【屬性填充】populateBean

AbstractAutowireCapableBeanFactory#populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    
    // 判斷實例化的 Bean 是否為空
	if (bw == null) {
	    // 返回是否有為此 Bean 定義的屬性值,如果有,則拋異常,提示 “無法將屬性值應(yīng)用于空實例”
		if (mbd.hasPropertyValues()) {
			throw new BeanCreationException(...);
		}
		// 沒有,則跳過屬性填充階段以獲取空實例
		else {
			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 后置處理器
        // @Autoware 的實現(xiàn)原理 
        // 這里涉及一個極其重要的后置處理器實現(xiàn) AutowiredAnnotationBeanPostProcessor,其主要用來處理 @Autowired 注解,這部分會在后面詳細討論
		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) {
        // 這里進行屬性的類型轉(zhuǎn)換,例如將字符串的 id 轉(zhuǎn)為數(shù)字的 id
	    // 執(zhí)行屬性注入,這里才真正的將屬性進行填充,將解析和類型轉(zhuǎn)換好的屬性列表(pvs)賦值到包裝對象(bw)上
		applyPropertyValues(beanName, mbd, bw, pvs);
	}
}
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
		
   	// ...
    
    // Create a deep copy, resolving any references for values.
    List<PropertyValue> deepCopy = new ArrayList<>(original.size());
    boolean resolveNecessary = false;
    for (PropertyValue pv : original) {
        // 遍歷解析到的每個屬性
        if (pv.isConverted()) {
            deepCopy.add(pv);
        }
        else {
            String propertyName = pv.getName();
            // 如果是 JDK 類型,返回的是 TypeStringValue
            // 如果是要注入其他的 Bean,則是 RuntimeBeanReference 類型
            Object originalValue = pv.getValue();
            // 這里是個重點,進行屬性的解析,如果是 JDK 類型則返回的對應(yīng) JDK 的類型
            // 如果是 RuntimeBeanReference,則會遞歸調(diào)用工廠的 getBean 獲取到要注入的對象
            Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
            Object convertedValue = resolvedValue;
            boolean convertible = bw.isWritableProperty(propertyName) &&
                !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
            if (convertible) {
                // 進行類型準(zhǔn)換
                convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
            }
            if (resolvedValue == originalValue) {
                if (convertible) {
                    // 將類型轉(zhuǎn)換好的數(shù)據(jù)賦值給 PropertyValue
                    pv.setConvertedValue(convertedValue);
                }
                deepCopy.add(pv);
            }
            else if (convertible && originalValue instanceof TypedStringValue &&
                     !((TypedStringValue) originalValue).isDynamic() &&
                     !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
                pv.setConvertedValue(convertedValue);
                deepCopy.add(pv);
            }
            else {
                resolveNecessary = true;
                deepCopy.add(new PropertyValue(pv, convertedValue));
            }
        }
    }
    if (mpvs != null && !resolveNecessary) {
        mpvs.setConverted();
    }

    try {
        // 這里才真正的對創(chuàng)建的包裝對象進行了屬性的賦值,底層肯定是用到了反射了
        bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    }
    catch (BeansException ex) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    }
}

【初始化】initializeBean

AbstractAutowireCapableBeanFactory#initializeBean

接著進入 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 的生命周期。

回調(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。

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

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) {

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

回調(diào) InitializingBean 的 afterPropertiesSet 方法

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

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

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) {
	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;
}

注意 Spring AOP 就是通過 BeanPostProcessor 來實現(xiàn)的,創(chuàng)建代理對象就是在初始化階段執(zhí)行 postProcessAfterInitialization 中完成的,有一個 AspectJAwareAdvisorAutoProxyCreator 這個類。

到這里,創(chuàng)建 Bean 的核心流程就討論結(jié)束,我這里做一個完整的歸納:

  1. 調(diào)用者通過 getBean 方法調(diào)用工廠獲取一個 Bean,傳入的 name 可以是 Bean 的 id;也可以是別名;也可以是 &name,表示獲取原始的 FactoryBean 對象。
  2. 通過一系列的方法重載,最后會到達 AbstractBeanFactory#doGetBean 方法處理,先要對傳入的 name 進行解析,解析出 id。
  3. 接下來會嘗試從單例緩存池中獲取已創(chuàng)建好的對象,Spring 底層提供了三級緩存(三個Map)體系來解決循環(huán)依賴的問題:singletonObjects、earlySingletonObjects、singletonFactories。
  4. 如果拿到了緩存數(shù)據(jù):對 FactoryBean 類型進行判定,決定是否直接返回緩存對象還是返回 FactoryBean.getObject()。
  5. 如果沒有拿到緩存數(shù)據(jù),說明要新建一個 Bean。
    • 首先進行父子容器的處理,當(dāng)父容器不為空并且獲取的 Bean 不在子容器定義時,從父容器遞歸獲取。
    • 將 Bean 標(biāo)記為已經(jīng)創(chuàng)建(或?qū)⒁獎?chuàng)建),即將 beanName 加入 alreadyCreated 集合。
    • 父子 Bean 的處理,將子標(biāo)簽 bean 的各個屬性合并到父標(biāo)簽,生成 RootBeanDefinition。
    • 處理 depends-on,若存在依賴則需要遞歸實例化依賴的 bean。
    • 根據(jù)不同的作用域創(chuàng)建 Bean 實例,分為單例、原型和其他,這三種創(chuàng)建的時候都會調(diào)用 createBean 方法,這個方法由 AbstractAutowireCapableBeanFactory 提供。
      • 首先需要處理 lookup-method 和 replaced-method。
      • 然后要將創(chuàng)建實例的職責(zé)交給 doCreateBean,這個方法大概有三個重要的步驟:
        1. 創(chuàng)建實例 createBeaninstance:使用工廠方法實例化還是使用構(gòu)造函數(shù),默認是無參構(gòu)造。這里返回的是包裝對象,里面還封裝了類型轉(zhuǎn)換器的信息。
        2. 屬性填充 populateBean:填充的時候設(shè)計到類型轉(zhuǎn)換,底層再通過反射對創(chuàng)建的包裝對象進行屬性賦值。
        3. 初始化 initializeBean:在這個步驟,分別回調(diào)了 Aware 系列接口、BeanPostProcessor 后置處理器、InitializingBean。
  6. 如果 getBean 的時候傳入了類型(getBean("user", User.clsss)),則需要進行類型轉(zhuǎn)換后返回。

以上就是超詳細解析Spring Bean的創(chuàng)建過程的詳細內(nèi)容,更多關(guān)于Spring Bean創(chuàng)建過程的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 啟動SpringBoot報錯Input length = 1問題及解決

    啟動SpringBoot報錯Input length = 1問題及解決

    這篇文章主要介紹了啟動SpringBoot報錯Input length = 1問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • SpringCloud Feign Jackson自定義配置方式

    SpringCloud Feign Jackson自定義配置方式

    這篇文章主要介紹了SpringCloud Feign Jackson自定義配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java大批量導(dǎo)出Excel數(shù)據(jù)的優(yōu)化過程

    Java大批量導(dǎo)出Excel數(shù)據(jù)的優(yōu)化過程

    幾十萬上百萬行的數(shù)據(jù)是很常見的。本文主要介紹了Java大批量導(dǎo)出Excel數(shù)據(jù)的優(yōu)化過程,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 關(guān)于SpringCloud?Ribbon替換輪詢算法問題

    關(guān)于SpringCloud?Ribbon替換輪詢算法問題

    Spring?Cloud?Ribbon是基于Netlix?Ribbon實現(xiàn)的一套客戶端負載均衡的工具。接下來通過本文給大家介紹SpringCloud?Ribbon替換輪詢算法問題,需要的朋友可以參考下
    2022-01-01
  • 一個簡單的Java文件讀取的進度條

    一個簡單的Java文件讀取的進度條

    這篇文章主要介紹了一個簡單的Java文件讀取的進度條,寫一個可以使用的?demo,涉及到了文件的相對路徑問題,需要的朋友可以參考下
    2023-04-04
  • Nacos單機版安裝啟動的全流程

    Nacos單機版安裝啟動的全流程

    這篇文章主要介紹了Nacos單機版安裝啟動的全流程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java操作PDF文件實現(xiàn)簽訂電子合同詳細教程

    Java操作PDF文件實現(xiàn)簽訂電子合同詳細教程

    這篇文章主要介紹了如何在PDF中加入電子簽章與電子簽名的過程,包括編寫Word文件、生成PDF、為PDF格式做表單、為表單賦值、生成文檔以及上傳到OBS中的步驟,需要的朋友可以參考下
    2025-01-01
  • IDEA運行Tomcat中文亂碼出現(xiàn)的各種問題

    IDEA運行Tomcat中文亂碼出現(xiàn)的各種問題

    這篇文章主要介紹了IDEA運行Tomcat中文亂碼的各種問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • java組裝樹形結(jié)構(gòu)List問題

    java組裝樹形結(jié)構(gòu)List問題

    這篇文章主要介紹了java組裝樹形結(jié)構(gòu)List問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Java面試題沖刺第三十天--數(shù)據(jù)庫(6)

    Java面試題沖刺第三十天--數(shù)據(jù)庫(6)

    這篇文章主要為大家分享了最有價值的三道關(guān)于數(shù)據(jù)庫的面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-09-09

最新評論