




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第基于springbootbean的實例化過程和屬性注入過程目錄bean的實例化過程和屬性注入過程bean實例化流程說明
bean的實例化過程和屬性注入過程
了解過springboot的加載流程的都知道springboot初始化bean都在refresh方法中。
這個方法代碼如下:
//Preparethiscontextforrefreshing.
prepareRefresh();
//Tellthesubclasstorefreshtheinternalbeanfactory.新建beanFactory
ConfigurableListableBeanFactorybeanFactory=obtainFreshBeanFactory();
//Preparethebeanfactoryforuseinthiscontext.
prepareBeanFactory(beanFactory);
try{
//Allowspost-processingofthebeanfactoryincontextsubclasses.
postProcessBeanFactory(beanFactory);
//Invokefactoryprocessorsregisteredasbeansinthecontext.
//加載實現beanFactoryPostProcessor的bean,bean定義的時候執行
invokeBeanFactoryPostProcessors(beanFactory);
//Registerbeanprocessorsthatinterceptbeancreation.
//加載實現了beanPostProcessor,在bean實例化前、后執行
registerBeanPostProcessors(beanFactory);
//Initializemessagesourceforthiscontext.
initMessageSource();
//Initializeeventmulticasterforthiscontext.
initApplicationEventMulticaster();
//Initializeotherspecialbeansinspecificcontextsubclasses.
onRefresh();
//Checkforlistenerbeansandregisterthem.
registerListeners();
//Instantiateallremaining(non-lazy-init)singletons.
//實例化非懶加載的bean、bean封裝、屬性注入、注解注入(主要使用BeanPostProcessor或子類實現)等
finishBeanFactoryInitialization(beanFactory);
//Laststep:publishcorrespondingevent.
finishRefresh();
這里我們主要看下finishBeanfactoryInitialization方法。此方法實現了bean的實例和屬性注入等。進入此方法的最后一行。
//Instantiateallremaining(non-lazy-init)singletons.
beanFactory.preInstantiateSingletons();
注釋寫的很清楚,實例化剩余非懶加載的bean。此方法的實現是核心類DefaultLisListableBeanFactory實現。這個方法中有個判斷:bean是否是beanFactory的實現類。
如果是則獲取bean的時候會從beanFactory實現類的getObject中獲取,我們重點看看getBean這個方法。
getBean是spring中最重要、最牛逼的方法之一,具體的邏輯是通過doGetBean方法處理的。
我們看下doGetBean方法,方法很長。我們分成幾個部分去看。
1、先判斷是否已經存在緩存中,代碼如下:
if(sharedInstance!=nullargs==null){
if(logger.isDebugEnabled()){
if(isSingletonCurrentlyInCreation(beanName)){
logger.debug("Returningeagerlycachedinstanceofsingletonbean'"+beanName+
"'thatisnotfullyinitializedyet-aconsequenceofacircularreference");
else{
logger.debug("Returningcachedinstanceofsingletonbean'"+beanName+"'");
bean=getObjectForBeanInstance(sharedInstance,name,beanName,null);
2、從父beanfactory中獲取
BeanFactoryparentBeanFactory=getParentBeanFactory();
if(parentBeanFactory!=null!containsBeanDefinition(beanName)){
//Notfound-checkparent.
StringnameToLookup=originalBeanName(name);
if(parentBeanFactoryinstanceofAbstractBeanFactory){
return((AbstractBeanFactory)parentBeanFactory).doGetBean(
nameToLookup,requiredType,args,typeCheckOnly);
elseif(args!=null){
//Delegationtoparentwithexplicitargs.
return(T)parentBeanFactory.getBean(nameToLookup,args);
else{
//Noargs-delegatetostandardgetBeanmethod.
returnparentBeanFactory.getBean(nameToLookup,requiredType);
}
3、直接創建RootBeanDefinition
//mark給此bean馬克一下。防止重復創建
if(!typeCheckOnly){
markBeanAsCreated(beanName);
try{
finalRootBeanDefinitionmbd=getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd,beanName,args);
//Guaranteeinitializationofbeansthatthecurrentbeandependson.
String[]dependsOn=mbd.getDependsOn();
if(dependsOn!=null){
for(Stringdep:dependsOn){
if(isDependent(beanName,dep)){
thrownewBeanCreationException(mbd.getResourceDescription(),beanName,
"Circulardepends-onrelationshipbetween'"+beanName+"'and'"+dep+"'");
registerDependentBean(dep,beanName);
getBean(dep);
4、是singleton還是prototype類型的,根據不同類型去實例化bean,代碼只貼了單例的類型:
//Createbeaninstance.
if(mbd.isSingleton()){
sharedInstance=getSingleton(beanName,()-{
try{
returncreateBean(beanName,mbd,args);
catch(BeansExceptionex){
//Explicitlyremoveinstancefromsingletoncache:Itmighthavebeenputthere
//eagerlybythecreationprocess,toallowforcircularreferenceresolution.
//Alsoremoveanybeansthatreceivedatemporaryreferencetothebean.
destroySingleton(beanName);
throwex;
bean=getObjectForBeanInstance(sharedInstance,name,beanName,mbd);
5、檢查bean的類型是否匹配
//Checkifrequiredtypematchesthetypeoftheactualbeaninstance.
if(requiredType!=null!requiredType.isInstance(bean)){
try{
TconvertedBean=getTypeConverter().convertIfNecessary(bean,requiredType);
if(convertedBean==null){
thrownewBeanNotOfRequiredTypeException(name,requiredType,bean.getClass());
returnconvertedBean;
catch(TypeMismatchExceptionex){
if(logger.isDebugEnabled()){
logger.debug("Failedtoconvertbean'"+name+"'torequiredtype'"+
ClassUtils.getQualifiedName(requiredType)+"'",ex);
thrownewBeanNotOfRequiredTypeException(name,requiredType,bean.getClass());
}
整個doGetBean方法改成這5個部分,重點看下第4個部分中的createBean和getObjectForBeanInstance方法。
1、createBean方法,里面主要是2個部分,bean直接是通過BeanPostProcessor的postProcessBeforeIntantiation方法獲取的。
注釋也是描述的很清楚:GiveBeanPostProcessorsachancetoreturnaproxyinsteadofthebeaninstance(英語渣渣不敢瞎翻譯誤導大家,理解就好)
代碼如下:
try{
//GiveBeanPostProcessorsachancetoreturnaproxyinsteadofthetargetbeaninstance.
Objectbean=resolveBeforeInstantiation(beanName,mbdToUse);
if(bean!=null){
returnbean;
catch(Throwableex){
thrownewBeanCreationException(mbdToUse.getResourceDescription(),beanName,
"BeanPostProcessorbeforeinstantiationofbeanfailed",ex);
第一個部分自己實現,那么createBean方法第2個部分毋庸置疑肯定是spring去實例化bean,代碼如下:
try{
ObjectbeanInstance=doCreateBean(beanName,mbdToUse,args);
if(logger.isDebugEnabled()){
logger.debug("Finishedcreatinginstanceofbean'"+beanName+"'");
returnbeanInstance;
}
又是do開頭的方法,說明這個也是一個創建方法,spring中一般do開頭的都是用于創建某個對象。跟著代碼走,看下doCreateBean方法,在查看此方法之前,可能需要了解下BeanWarpper這個封裝類。bean的封裝、屬性注入等都是用BeanWarpper去完成的。
看下代碼:
//Instantiatethebean.
BeanWrapperinstanceWrapper=null;
if(mbd.isSingleton()){
instanceWrapper=this.factoryBeanInstanceCache.remove(beanName);
if(instanceWrapper==null){
instanceWrapper=createBeanInstance(beanName,mbd,args);
}
進入createBeanInstance方法中,就是調用構造器去實例化bean,返回beanWrapper。通過構造器獲取實例代碼如下:
//Needtodeterminetheconstructor...
Constructor[]ctors=determineConstructorsFromBeanPostProcessors(beanClass,beanName);
if(ctors!=null||
mbd.getResolvedAutowireMode()==RootBeanDefinition.AUTOWIRE_CONSTRUCTOR||
mbd.hasConstructorArgumentValues()||!ObjectUtils.isEmpty(args)){
returnautowireConstructor(beanName,mbd,ctors,args);
//Nospecialhandling:simplyuseno-argconstructor.
returninstantiateBean(beanName,mbd);
這里實例化我一開始以為就是簡單的反射,后面我點進去時候發現里面一直提策略實例化,我目前了解的是可以解決Override的問題等。如果有興趣的可以自行查看。到這里為止。我們終于實例化bean了。下面看下第二步bean的屬性注入等。
代碼如下:
ObjectexposedObject=bean;
try{
populateBean(beanName,mbd,instanceWrapper);
exposedObject=initializeBean(beanName,exposedObject,mbd);
catch(Throwableex){
if(exinstanceofBeanCreationExceptionbeanName.equals(((BeanCreationException)ex).getBeanName())){
throw(BeanCreationException)ex;
else{
thrownewBeanCreationException(
mbd.getResourceDescription(),beanName,"Initializationofbeanfailed",ex);
}
populateBean方法名稱就暴露他是干啥的:填充bean。我放一段比較重要的部分:
if(hasInstAwareBpps||needsDepCheck){
if(pvs==null){
pvs=mbd.getPropertyValues();
PropertyDescriptor[]filteredPds=filterPropertyDescriptorsForDependencyCheck(bw,mbd.allowCaching);
if(hasInstAwareBpps){
for(BeanPostProcessorbp:getBeanPostProcessors()){
if(bpinstanceofInstantiationAwareBeanPostProcessor){
InstantiationAwareBeanPostProcessoribp=(InstantiationAwareBeanPostProcessor)bp;
pvs=ibp.postProcessPropertyValues(pvs,filteredPds,bw.getWrappedInstance(),beanName);
if(pvs==null){
return;
if(needsDepCheck){
checkDependencies(beanName,mbd,filteredPds,pvs);
}
這段代碼貌似沒有什么注入、填充什么的,我們看下InstantiationAwareBeanPostProcessor這個接口,發現這個接口有個很熟悉的實現類是:AutowiredAnnotationBeanPostProcessor。這個類的方法中我們看到終于看到了jnject方法。但是在inject之前需要調用下findAutowiringMatedata方法獲取一下元數據:
//Fallbacktoclassnameascachekey,forbackwardscompatibilitywithcustomcallers.
StringcacheKey=(StringUtils.hasLength(beanName)beanName:clazz.getName());
//Quickcheckontheconcurrentmapfirst,withminimallocking.
InjectionMetadatametadata=this.injectionMetadataCache.get(cacheKey);
if(InjectionMetadata.needsRefresh(metadata,clazz)){
synchronized(this.injectionMetadataCache){
metadata=this.injectionMetadataCache.get(cacheKey);
if(InjectionMetadata.needsRefresh(metadata,clazz)){
if(metadata!=null){
metadata.clear(pvs);
metadata=buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey,metadata);
returnmetadata;
那么問題又來了,這個injectionMetadataCache集合值是從那里來的呢?AutowiredAnnotationBeanPostProcessor實現了MergeBeandefinitionPostProcessor,那么就好了,肯定是在bean實例的時候調用了postProcessMergedBeanDefintion這個方法。
果然在doCreateBean方法中有這么一段:
//Allowpost-processorstomodifythemergedbeandefinition.
synchronized(mbd.postProcessingLock){
if(!mbd.postProcessed){
try{
//通過BeanPostProcessor將需要注解的元數據放到Map中
applyMergedBeanDefinitionPostProcessors(mbd,beanType,beanName);
catch(Throwableex){
thrownewBeanCreationException(mbd.getResourceDescription(),beanName,
"Post-processingofmergedbeandefinitionfailed",ex);
mbd.postProcessed=true;
}
哎,spring縝密啊。元數據有了,下面我們看下element.inject()方法是如何操作的:
if(this.isField){
Fieldfield=(Field)this.member;
ReflectionUtils.makeAccessible(field);
field.set(target,getResourceToInject(target,requestingBeanName));
else{
if(checkPropertySkipping(pvs)){
return;
try{
Methodmethod=(Method)this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target,getResourceToInject(target,requestingBeanName));
catch(InvocationTargetExceptionex){
throwex.getTargetException();
}
方法簡單明了,直接使用反射將值set到屬性中,至此bean的實例、屬性注入基本完成,下面我們回頭來看doGetBean的另一個方法getObjectForBeanInstance。
2、getObjectForBeanInstance方法。對于是FactoryBean類型的bean通過getObject獲取到bean的代理實例,跟著方法一直走下去會到getObejct()方法中。
if(System.getSecurityManager()!=null){
AccessControlContextacc=getAccessControlContext();
try{
object=AccessController.doPrivileged((PrivilegedExceptionActionObject)factory::getObject,acc);
catch(PrivilegedActionExceptionpae){
throwpae.getException();
else{
//從FactoryBean實現bean中getObejct獲取到bean
object=factory.getObject();
}
到此finishBeanfactoryInitialization方法執行結束!
bean實例化流程說明
bean實例化流程流程是在onRefresh方法的finishBeanFactoryInitialization中。進入該方法
protectedvoidfinishBeanFactoryInitialization(ConfigurableListableBeanFactorybeanFactory){
//Initializeconversionserviceforthiscontext.
if(beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME,ConversionService.class)){
beanFactory.setConversionServi
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年城市軌道交通起重裝卸機械操作工職業技能鑒定試卷
- 2025年國家安全生產監督管理總局公務員錄用考試面試真題試卷(結構化小組)
- 2025年高壓成套電器項目申請報告
- 2025年保育員(三級)考試試卷深度分析與備考指南
- 與離婚協議書補充協議
- 2025年PETS二級英語聽力理解能力提升試卷(含2025年真題解析)
- 和珅的做人之道
- 2025年保育員實操技能試卷:幼兒教育心理輔導實踐創新案例分析
- 2025年電子商務師(高級)職業技能鑒定試卷:熱點問題解答與案例分析
- 2025年服裝設計師(服裝設計實踐應用)考試試題
- GB/T 14294-1993組合式空調機組
- GA 1517-2018金銀珠寶營業場所安全防范要求
- 提高痰留取成功率PDCA課件
- 一級建造師繼續教育考試題(重點)
- 組合導航與融合導航解析課件
- 伊金霍洛旗事業編招聘考試《行測》歷年真題匯總及答案解析精選V
- 深基坑支護工程驗收表
- 工期的保證體系及保證措施
- 顱腦CT影像課件
- 同濟大學論文答辯通用PPT模板
- 課程設計-整體式肋梁樓蓋設計
評論
0/150
提交評論