版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第基于springbootbean的實(shí)例化過(guò)程和屬性注入過(guò)程目錄bean的實(shí)例化過(guò)程和屬性注入過(guò)程bean實(shí)例化流程說(shuō)明
bean的實(shí)例化過(guò)程和屬性注入過(guò)程
了解過(guò)springboot的加載流程的都知道springboot初始化bean都在refresh方法中。
這個(gè)方法代碼如下:
//Preparethiscontextforrefreshing.
prepareRefresh();
//Tellthesubclasstorefreshtheinternalbeanfactory.新建beanFactory
ConfigurableListableBeanFactorybeanFactory=obtainFreshBeanFactory();
//Preparethebeanfactoryforuseinthiscontext.
prepareBeanFactory(beanFactory);
try{
//Allowspost-processingofthebeanfactoryincontextsubclasses.
postProcessBeanFactory(beanFactory);
//Invokefactoryprocessorsregisteredasbeansinthecontext.
//加載實(shí)現(xiàn)beanFactoryPostProcessor的bean,bean定義的時(shí)候執(zhí)行
invokeBeanFactoryPostProcessors(beanFactory);
//Registerbeanprocessorsthatinterceptbeancreation.
//加載實(shí)現(xiàn)了beanPostProcessor,在bean實(shí)例化前、后執(zhí)行
registerBeanPostProcessors(beanFactory);
//Initializemessagesourceforthiscontext.
initMessageSource();
//Initializeeventmulticasterforthiscontext.
initApplicationEventMulticaster();
//Initializeotherspecialbeansinspecificcontextsubclasses.
onRefresh();
//Checkforlistenerbeansandregisterthem.
registerListeners();
//Instantiateallremaining(non-lazy-init)singletons.
//實(shí)例化非懶加載的bean、bean封裝、屬性注入、注解注入(主要使用BeanPostProcessor或子類實(shí)現(xiàn))等
finishBeanFactoryInitialization(beanFactory);
//Laststep:publishcorrespondingevent.
finishRefresh();
這里我們主要看下finishBeanfactoryInitialization方法。此方法實(shí)現(xiàn)了bean的實(shí)例和屬性注入等。進(jìn)入此方法的最后一行。
//Instantiateallremaining(non-lazy-init)singletons.
beanFactory.preInstantiateSingletons();
注釋寫(xiě)的很清楚,實(shí)例化剩余非懶加載的bean。此方法的實(shí)現(xiàn)是核心類DefaultLisListableBeanFactory實(shí)現(xiàn)。這個(gè)方法中有個(gè)判斷:bean是否是beanFactory的實(shí)現(xiàn)類。
如果是則獲取bean的時(shí)候會(huì)從beanFactory實(shí)現(xiàn)類的getObject中獲取,我們重點(diǎn)看看getBean這個(gè)方法。
getBean是spring中最重要、最牛逼的方法之一,具體的邏輯是通過(guò)doGetBean方法處理的。
我們看下doGetBean方法,方法很長(zhǎng)。我們分成幾個(gè)部分去看。
1、先判斷是否已經(jīng)存在緩存中,代碼如下:
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、直接創(chuàng)建RootBeanDefinition
//mark給此bean馬克一下。防止重復(fù)創(chuàng)建
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類型的,根據(jù)不同類型去實(shí)例化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());
}
整個(gè)doGetBean方法改成這5個(gè)部分,重點(diǎn)看下第4個(gè)部分中的createBean和getObjectForBeanInstance方法。
1、createBean方法,里面主要是2個(gè)部分,bean直接是通過(guò)BeanPostProcessor的postProcessBeforeIntantiation方法獲取的。
注釋也是描述的很清楚:GiveBeanPostProcessorsachancetoreturnaproxyinsteadofthebeaninstance(英語(yǔ)渣渣不敢瞎翻譯誤導(dǎo)大家,理解就好)
代碼如下:
try{
//GiveBeanPostProcessorsachancetoreturnaproxyinsteadofthetargetbeaninstance.
Objectbean=resolveBeforeInstantiation(beanName,mbdToUse);
if(bean!=null){
returnbean;
catch(Throwableex){
thrownewBeanCreationException(mbdToUse.getResourceDescription(),beanName,
"BeanPostProcessorbeforeinstantiationofbeanfailed",ex);
第一個(gè)部分自己實(shí)現(xiàn),那么createBean方法第2個(gè)部分毋庸置疑肯定是spring去實(shí)例化bean,代碼如下:
try{
ObjectbeanInstance=doCreateBean(beanName,mbdToUse,args);
if(logger.isDebugEnabled()){
logger.debug("Finishedcreatinginstanceofbean'"+beanName+"'");
returnbeanInstance;
}
又是do開(kāi)頭的方法,說(shuō)明這個(gè)也是一個(gè)創(chuàng)建方法,spring中一般do開(kāi)頭的都是用于創(chuàng)建某個(gè)對(duì)象。跟著代碼走,看下doCreateBean方法,在查看此方法之前,可能需要了解下BeanWarpper這個(gè)封裝類。bean的封裝、屬性注入等都是用BeanWarpper去完成的。
看下代碼:
//Instantiatethebean.
BeanWrapperinstanceWrapper=null;
if(mbd.isSingleton()){
instanceWrapper=this.factoryBeanInstanceCache.remove(beanName);
if(instanceWrapper==null){
instanceWrapper=createBeanInstance(beanName,mbd,args);
}
進(jìn)入createBeanInstance方法中,就是調(diào)用構(gòu)造器去實(shí)例化bean,返回beanWrapper。通過(guò)構(gòu)造器獲取實(shí)例代碼如下:
//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);
這里實(shí)例化我一開(kāi)始以為就是簡(jiǎn)單的反射,后面我點(diǎn)進(jìn)去時(shí)候發(fā)現(xiàn)里面一直提策略實(shí)例化,我目前了解的是可以解決Override的問(wèn)題等。如果有興趣的可以自行查看。到這里為止。我們終于實(shí)例化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);
}
這段代碼貌似沒(méi)有什么注入、填充什么的,我們看下InstantiationAwareBeanPostProcessor這個(gè)接口,發(fā)現(xiàn)這個(gè)接口有個(gè)很熟悉的實(shí)現(xiàn)類是:AutowiredAnnotationBeanPostProcessor。這個(gè)類的方法中我們看到終于看到了jnject方法。但是在inject之前需要調(diào)用下findAutowiringMatedata方法獲取一下元數(shù)據(jù):
//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;
那么問(wèn)題又來(lái)了,這個(gè)injectionMetadataCache集合值是從那里來(lái)的呢?AutowiredAnnotationBeanPostProcessor實(shí)現(xiàn)了MergeBeandefinitionPostProcessor,那么就好了,肯定是在bean實(shí)例的時(shí)候調(diào)用了postProcessMergedBeanDefintion這個(gè)方法。
果然在doCreateBean方法中有這么一段:
//Allowpost-processorstomodifythemergedbeandefinition.
synchronized(mbd.postProcessingLock){
if(!mbd.postProcessed){
try{
//通過(guò)BeanPostProcessor將需要注解的元數(shù)據(jù)放到Map中
applyMergedBeanDefinitionPostProcessors(mbd,beanType,beanName);
catch(Throwableex){
thrownewBeanCreationException(mbd.getResourceDescription(),beanName,
"Post-processingofmergedbeandefinitionfailed",ex);
mbd.postProcessed=true;
}
哎,spring縝密啊。元數(shù)據(jù)有了,下面我們看下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();
}
方法簡(jiǎn)單明了,直接使用反射將值set到屬性中,至此bean的實(shí)例、屬性注入基本完成,下面我們回頭來(lái)看doGetBean的另一個(gè)方法getObjectForBeanInstance。
2、getObjectForBeanInstance方法。對(duì)于是FactoryBean類型的bean通過(guò)getObject獲取到bean的代理實(shí)例,跟著方法一直走下去會(huì)到getObejct()方法中。
if(System.getSecurityManager()!=null){
AccessControlContextacc=getAccessControlContext();
try{
object=AccessController.doPrivileged((PrivilegedExceptionActionObject)factory::getObject,acc);
catch(PrivilegedActionExceptionpae){
throwpae.getException();
else{
//從FactoryBean實(shí)現(xiàn)bean中g(shù)etObejct獲取到bean
object=factory.getObject();
}
到此finishBeanfactoryInitialization方法執(zhí)行結(jié)束!
bean實(shí)例化流程說(shuō)明
bean實(shí)例化流程流程是在onRefresh方法的finishBeanFactoryInitialization中。進(jìn)入該方法
protectedvoidfinishBeanFactoryInitialization(ConfigurableListableBeanFactorybeanFactory){
//Initializeconversionserviceforthiscontext.
if(beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME,ConversionService.class)){
beanFactory.setConversionServi
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025廣東江門(mén)市城建集團(tuán)有限公司公路運(yùn)營(yíng)分公司招聘1人備考題庫(kù)附答案
- 2025年中船凌久航信科技(武漢)有限公司招聘(公共基礎(chǔ)知識(shí))測(cè)試題附答案
- 2025年哈爾濱日?qǐng)?bào)社新媒體中心招聘若干人備考題庫(kù)附答案
- 2026浙江臺(tái)州職業(yè)技術(shù)學(xué)院高層次人才招聘38人筆試模擬試題及答案解析
- 2025廣東茂名市高州市人民政府辦公室選調(diào)公務(wù)員5人備考題庫(kù)附答案
- 2025年聊城臨清市人才回引(17人)備考題庫(kù)附答案
- 2025廣東河源東源縣衛(wèi)生健康局招聘高層次和急需緊缺人才35人(公共基礎(chǔ)知識(shí))綜合能力測(cè)試題附答案
- 2026甘肅酒泉市敦煌市國(guó)有資產(chǎn)事務(wù)中心遴選市屬國(guó)有企業(yè)外部董事人才庫(kù)人選筆試備考試題及答案解析
- 2026甘肅銀行校園招聘筆試備考試題及答案解析
- 2025秋人教版道德與法治八年級(jí)上冊(cè)3.1網(wǎng)絡(luò)改變世界課件
- 工程維保三方合同
- 地鐵車(chē)輛檢修安全培訓(xùn)
- 造血干細(xì)胞移植臨床應(yīng)用和新進(jìn)展課件
- GB/T 10802-2023通用軟質(zhì)聚氨酯泡沫塑料
- 黑布林英語(yǔ)閱讀初一年級(jí)16《柳林風(fēng)聲》譯文和答案
- 杰青優(yōu)青學(xué)術(shù)項(xiàng)目申報(bào)答辯PPT模板
- 宿舍入住申請(qǐng)書(shū)
- 深圳中核海得威生物科技有限公司桐城分公司碳13-尿素原料藥項(xiàng)目環(huán)境影響報(bào)告書(shū)
- 2023年全國(guó)高考體育單招文化考試數(shù)學(xué)試卷真題及答案
- GB/T 28733-2012固體生物質(zhì)燃料全水分測(cè)定方法
- GB/T 14404-2011剪板機(jī)精度
評(píng)論
0/150
提交評(píng)論