GetBean源碼部分
protected??T?doGetBean(finalStringname,@NullablefinalClass?requiredType,
@NullablefinalObject[]?args,?boolean?typeCheckOnly)?throws?BeansException?{
//會包括解析別名等操作
finalStringbeanName?=?transformedBeanName(name);
Objectbean;
//?先檢查單例列表中是否已經注冊了這個bean
ObjectsharedInstance?=?getSingleton(beanName);
if(sharedInstance?!=null&&?args?==null)?{
bean?=?getObjectForBeanInstance(sharedInstance,?name,?beanName,null);
}
else{
//?檢查bean是否并發(fā)被創(chuàng)建
if(isPrototypeCurrentlyInCreation(beanName))?{
thrownewBeanCurrentlyInCreationException(beanName);
}
//?檢查是否在父類工廠中,邏輯和這個差不多,這里省略....
//標記bean正在被創(chuàng)建
if(!typeCheckOnly)?{
markBeanAsCreated(beanName);
}
try{
//合并父類中的方法及屬性,下面會細講??????????????????????
finalRootBeanDefinition?mbd?=?getMergedLocalBeanDefinition(beanName);
//檢查這個bean是否為抽象類
checkMergedBeanDefinition(mbd,?beanName,?args);
//?這里是為了保證獲取的bean的依賴都需要先生成
String[]?dependsOn?=?mbd.getDependsOn();
if(dependsOn?!=null)?{
for(Stringdep?:?dependsOn)?{
if(isDependent(beanName,?dep))?{
thrownewBeanCreationException(mbd.getResourceDescription(),?beanName,
"Circular?depends-on?relationship?between?'"+?beanName?+"'?and?'"+?dep?+"'");
}
registerDependentBean(dep,?beanName);
try{
getBean(dep);
}
catch(NoSuchBeanDefinitionException?ex){
throwex;
}
}
}
//?創(chuàng)建單例的bean,看下方的createBean方法
if(mbd.isSingleton())?{
sharedInstance?=?getSingleton(beanName,?()?->?{
try{
returncreateBean(beanName,?mbd,?args);
}
catch(BeansException?ex)?{
destroySingleton(beanName);
throwex;
}
});
bean?=?getObjectForBeanInstance(sharedInstance,?name,?beanName,?mbd);
}
elseif(mbd.isPrototype())?{
//?It's?a?prototype?->?create?a?new?instance.
ObjectprototypeInstance?=null;
try{
beforePrototypeCreation(beanName);
prototypeInstance?=?createBean(beanName,?mbd,?args);
}
finally{
afterPrototypeCreation(beanName);
}
bean?=?getObjectForBeanInstance(prototypeInstance,?name,?beanName,?mbd);
}
else{
StringscopeName?=?mbd.getScope();
finalScope?scope?=this.scopes.get(scopeName);
if(scope?==null)?{
thrownewIllegalStateException("No?Scope?registered?for?scope?name?'"+?scopeName?+"'");
}
try{
ObjectscopedInstance?=?scope.get(beanName,?()?->?{
beforePrototypeCreation(beanName);
try{
returncreateBean(beanName,?mbd,?args);
}
finally{
afterPrototypeCreation(beanName);
}
});
bean?=?getObjectForBeanInstance(scopedInstance,?name,?beanName,?mbd);
}
catch(IllegalStateException?ex)?{
thrownewBeanCreationException(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);
throwex;
}
}
//?檢查需要的類型和實際傳參類型是否一致.?這里省略....
return(T)?bean;
}
整個操作大概是以下幾步:
獲取實際的beanName,其中會處理帶&號前綴的beanName视事,并解析別名讶坯。
檢查單例列表中是否存在該beanName的bean冰悠,若存在則無需走下面的創(chuàng)建bean的流程裹芝。
若單例列表中并不存在此bean咙崎,則檢查是否有并發(fā)創(chuàng)建弟跑。這里的判斷只針對scope為prototype類型的bean廊蜒。
檢查bean是否存在于父類工廠中,若存在胯盯,則走父類工廠的getBean流程懈费。向上委托,保證容器中只會存在一個同名的bean博脑。
標記bean正在被創(chuàng)建憎乙。
如果有父類,這里會遞歸合并父類的方法以及屬性叉趣。并會用自己重寫的方法覆蓋其父類的方法泞边。合并完成并檢查這個bean的是否是抽象類。
如果該bean上有注解@DependsOn,或者配置文件上配置有該屬性,則需保證該bean的所有依賴需要先在容器內注冊疗杉。
分單例和原型以及其他scope類型來創(chuàng)建bean阵谚。
檢查需要的類型和生成的bean類型是否一致。
返回創(chuàng)建好的bean烟具。
getSingleton源碼部分(beanName梢什,allowEarlyReference)
這里的singletonObjects是一個緩存了beanName和bean的Map,若存在,直接返回净赴。
不存在绳矩,則檢查是否這個bean是否正在創(chuàng)建的過程中罩润,先檢查earlySingletonObjects這個容器,這個容器里面放著的是已經構造完成但是沒有注入屬性的對象玖翅,若存在,也會直接返回割以。
嘗試著從singletonFactories中獲取金度,然后調用getObject方法去獲取對象。并將獲取到的對象放到earlySingletonObjects容器中严沥,然后從singletonFactories容器中移除猜极。
這里這么設計是為了解決循環(huán)依賴的問題。若A依賴B消玄,B依賴C跟伏,C又依賴A,這樣三個bean就形成了一個環(huán)(這里只是針對set方法注入的bean,構造器注入還是會有循環(huán)依賴的問題而拋出異常的)翩瓜,spring會將創(chuàng)建的bean實例提前暴露在緩存中受扳,一旦下一個bean創(chuàng)建的時候需要依賴上個bean,則直接使用ObjectFactory來獲取bean兔跌。
這里舉個生活中的例子闡述下:就拿建一個小區(qū)房來說勘高,建房子是一個很復雜的工序,但是咱們只要把架子搭好,告訴大家這塊地是用來建這個房子的就行华望。至于其他裝修蕊蝗,家私等等東西都可以后面再進行補充。咱們不能搭架子的時候去放家具吧赖舟,這樣整個都會亂套蓬戚,也不符合常理。(這里房子的框架是咱們程序中的一個對象A宾抓,家具是另一個對象B碌更,A依賴B,B依賴A)
循環(huán)依賴
相關的邏輯有用到以下代碼段:
每次singleton bean創(chuàng)造之前都會調用的方法洞慎,在singletonsCurrentlyInCreation容器中加入這個bean的beanName,標記這個bean正在創(chuàng)建中痛单,供后期生成ObjectFactory。這里有個inCreationCheckExclusions容器劲腿,在這里我理解為屬于該容器的bean必須要初始化完成才允許被獲取旭绒。也就是說,添加進該容器后bean便不會允許早期的循環(huán)依賴了焦人。
上面的代碼片段的調用在doCreateBean源碼中(排在bean對象創(chuàng)建之后和屬性注入之前)挥吵,可以觀察到要執(zhí)行addSingletonFactory方法需要滿足三個條件:
這個bean是單例的,
允許循環(huán)依賴花椭,
這個bean正在被創(chuàng)建的過程中忽匈。
在滿足這三個條件的情況下,會在singletonFactories容器中緩存一個生成該bean的工廠矿辽,將其提前暴露出去丹允。這里關注下getEarlyBeanReference(beanName, mbd, bean)這個方法,實際上ObjectFactory中getObject方法調用的也是這個方法袋倔。
getMergedBeanDefinition源碼部分
看這部分之前雕蔽,首先得明白BeanDefinition是用來干什么的,這個類會在整個源碼解析過程中出現(xiàn)無數(shù)次宾娜。Spring把BeanDefinition定義成IOC容器的內部數(shù)據結構批狐,實際上它也就是POJO對象在IOC容器中的抽象,通過這個對象前塔,IOC容器能很方便的對Bean進行管理嚣艇,包括利用它進行屬性的注入等等…
protectedRootBeanDefinitiongetMergedBeanDefinition(
String?beanName,?BeanDefinition?bd,?@Nullable?BeanDefinition?containingBd)
throwsBeanDefinitionStoreException
{
synchronized(this.mergedBeanDefinitions)?{
RootBeanDefinition?mbd?=null;
//?重新去獲取一次,有可能該BeanDefinition已經生成
if(containingBd?==null)?{
mbd?=this.mergedBeanDefinitions.get(beanName);
}
if(mbd?==null)?{
if(bd.getParentName()?==null)?{
//?沒有父類則深拷貝一個RootBeanDefinition
if(bdinstanceofRootBeanDefinition)?{
mbd?=?((RootBeanDefinition)?bd).cloneBeanDefinition();
}
else{
mbd?=newRootBeanDefinition(bd);
}
}
else{
//?有父類則需要先獲取父類的BeanDefinition华弓,流程和獲取子類的BeanDefinition一致
BeanDefinition?pbd;
try{
String?parentBeanName?=?transformedBeanName(bd.getParentName());
if(!beanName.equals(parentBeanName))?{
pbd?=?getMergedBeanDefinition(parentBeanName);
}
else{
BeanFactory?parent?=?getParentBeanFactory();
if(parentinstanceofConfigurableBeanFactory)?{
pbd?=?((ConfigurableBeanFactory)?parent).getMergedBeanDefinition(parentBeanName);
}
else{
thrownewNoSuchBeanDefinitionException(parentBeanName,
"Parent?name?'"+?parentBeanName?+"'?is?equal?to?bean?name?'"+?beanName?+
"':?cannot?be?resolved?without?an?AbstractBeanFactory?parent");
}
}
}
catch(NoSuchBeanDefinitionException?ex)?{
thrownewBeanDefinitionStoreException(bd.getResourceDescription(),?beanName,
"Could?not?resolve?parent?bean?definition?'"+?bd.getParentName()?+"'",?ex);
}
//這里進行深拷貝食零,并將子類重寫的方法和屬性進行覆蓋
mbd?=newRootBeanDefinition(pbd);
mbd.overrideFrom(bd);
}
//?若前面沒配置scope類型,這里設置為單例范圍
if(!StringUtils.hasLength(mbd.getScope()))?{
mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
}
//?這里對內部類做了一些處理该抒,若包含它的bean不是單例的慌洪,則該bean也將不會是單例的
if(containingBd?!=null&&?!containingBd.isSingleton()?&&?mbd.isSingleton())?{
mbd.setScope(containingBd.getScope());
}
//?將生產的BeanDefinition?緩存起來
if(containingBd?==null&&?isCacheBeanMetadata())?{
this.mergedBeanDefinitions.put(beanName,?mbd);
}
}
returnmbd;
}
}
在mergedBeanDefinitions同步的情況下再次讀取緩存顶燕,防止該BeanDefinition已經被合并過了。
檢查是否有父類冈爹,若有父類涌攻,則必須遞歸去合并BeanDefinition。
將子類重寫后的方法覆蓋到定義的BeanDefinition中频伤。
設置scope類型恳谎。
將生成的BeanDefinition緩存起來。
registerDependentBean源碼部分
這一部分應該還是很容易理解的憋肖,這里面出現(xiàn)了兩個Map,一個是dependentBeanMap因痛,它主要用來裝載鍵為beanName值為dependentBeanName的容器,另一個dependenciesForBeanMap是用來裝載鍵為dependentBeanName值為beanName的容器岸更,這樣可以方便我們觀察一個類需要組裝哪些依賴鸵膏,然后這個類同時是哪些類的依賴。
getSingleton源碼部分(beanName怎炊,singletonFactory)
publicObject?getSingleton(String?beanName,?ObjectFactory?singletonFactory)?{
Assert.notNull(beanName,"Bean?name?must?not?be?null");
synchronized?(this.singletonObjects)?{
//先去singletonObjects容器中去獲取谭企,能獲取到就直接返回了
Object?singletonObject?=this.singletonObjects.get(beanName);
if(singletonObject?==null)?{
//調用destroySingletons方法singletonsCurrentlyInDestruction屬性才會變成true
if(this.singletonsCurrentlyInDestruction)?{
thrownew?Exception("xx"));
}
//這里會將beanName緩存到singletonsCurrentlyInCreation集合中
beforeSingletonCreation(beanName);
boolean?newSingleton?=false;
boolean?recordSuppressedExceptions?=?(this.suppressedExceptions?==null);
if(recordSuppressedExceptions)?{
this.suppressedExceptions?=?new?LinkedHashSet<>();
}
try{
//這里會觸發(fā)下面的createBean方法
singletonObject?=?singletonFactory.getObject();
newSingleton?=true;
}
catch(IllegalStateException?ex)?{
//?如果是與此同時被創(chuàng)建了,則直接獲取评肆,如果能獲取到值不為null债查,則正常返回。
//(注意這里捕獲異常正常返回的話就不會走下面的addSingleton方法了瓜挽。)
singletonObject?=this.singletonObjects.get(beanName);
if(singletonObject?==null)?{
throwex;
}
}
catch(BeanCreationException?ex)?{
if(recordSuppressedExceptions)?{
for(Exception?suppressedException?:this.suppressedExceptions)?{
ex.addRelatedCause(suppressedException);
}
}
throwex;
}
finally{
if(recordSuppressedExceptions)?{
this.suppressedExceptions?=null;
}
//這里會將beanName從singletonsCurrentlyInCreation集合中移除
afterSingletonCreation(beanName);
}
if(newSingleton)?{
//添加到singletonObjects和registeredSingletons緩存中盹廷,并從singletonFactories和earlySingletonObjects中移除
addSingleton(beanName,?singletonObject);
}
}
returnsingletonObject;
}
}
直接去singletonObjects中獲取,獲取到了便直接返回久橙。
獲取不到俄占,先將beanName緩存到singletonsCurrentlyInCreation集合中,作為標記表示該bean正在被創(chuàng)建的過程中剥汤。
觸發(fā)createBean方法去創(chuàng)建bean颠放,這里可以去看一下ObjectFactory這個接口工廠,這里是對getObject方法的一個回調(AbstractAutowireCapableBeanFactory中的createBean方法)吭敢。
創(chuàng)建bean的過程中在不出異常的情況下便會進行下圖的操作后并返回,也就操作了幾個容器的緩存而已暮芭。
createBean源碼部分
這一塊不是很復雜鹿驼,復雜的地方在doCreateBean這個方法中。
protectedObjectcreateBean(StringbeanName,?RootBeanDefinition?mbd,@NullableObject[]?args)
throws?BeanCreationException?{
RootBeanDefinition?mbdToUse?=?mbd;
//?要保證RootBeanDefinition的beanClass是存在的
Class?resolvedClass?=?resolveBeanClass(mbd,?beanName);
if(resolvedClass?!=null&&?!mbd.hasBeanClass()?&&?mbd.getBeanClassName()?!=null)?{
mbdToUse?=newRootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
//?這一塊沒什么研究辕宏,注解意思是(檢查所有帶有override的方法是否都是存在的)
try{
mbdToUse.prepareMethodOverrides();
}
catch(BeanDefinitionValidationException?ex)?{
}
try{
//這一塊我猜測大概是看咱們自己有提供實例化的方法不畜晰,若有,則不會走下面的doCreateBean方法瑞筐。
Objectbean?=?resolveBeforeInstantiation(beanName,?mbdToUse);
if(bean?!=null)?{
returnbean;
}
}
catch(Throwable?ex)?{
}
try{
//創(chuàng)建bean的真正方法
ObjectbeanInstance?=?doCreateBean(beanName,?mbdToUse,?args);
}
returnbeanInstance;
}
catch(Exception?e){
throwe;
}
}
doCreateBean源碼部分
protectedObjectdoCreateBean(finalStringbeanName,finalRootBeanDefinition?mbd,final@NullableObject[]?args)
throws?BeanCreationException?{
//?Instantiate?the?bean.
BeanWrapper?instanceWrapper?=null;
if(mbd.isSingleton())?{
instanceWrapper?=this.factoryBeanInstanceCache.remove(beanName);
}
if(instanceWrapper?==null)?{
//?創(chuàng)建這個bean,真正構建時有分兩種情況凄鼻,jdk反射和cglib動態(tài)代理
instanceWrapper?=?createBeanInstance(beanName,?mbd,?args);
}
finalObjectbean?=?instanceWrapper.getWrappedInstance();
Class?beanType?=?instanceWrapper.getWrappedClass();
if(beanType?!=?NullBean.class)?{
mbd.resolvedTargetType?=?beanType;
}
//?允許后置處理器來修改這個BeanDefinition
synchronized?(mbd.postProcessingLock)?{
if(!mbd.postProcessed)?{
try{
applyMergedBeanDefinitionPostProcessors(mbd,?beanType,?beanName);
}
catch(Throwable?ex)?{
thrownewBeanCreationException(mbd.getResourceDescription(),?beanName,
"Post-processing?of?merged?bean?definition?failed",?ex);
}
mbd.postProcessed?=true;
}
}
//?用來解決循環(huán)依賴問題的,上面已經有過詳細解釋了】榘觯看上面循環(huán)依賴模塊
boolean?earlySingletonExposure?=?(mbd.isSingleton()?&&this.allowCircularReferences?&&
isSingletonCurrentlyInCreation(beanName));
if(earlySingletonExposure)?{
if(logger.isTraceEnabled())?{
logger.trace("Eagerly?caching?bean?'"+?beanName?+
"'?to?allow?for?resolving?potential?circular?references");
}
addSingletonFactory(beanName,?()?->?getEarlyBeanReference(beanName,?mbd,?bean));
}
//?Initialize?the?bean?instance.
ObjectexposedObject?=?bean;
try{
//進行屬性的注入闰非,調用bean的set方法進行字段的初始化
populateBean(beanName,?mbd,?instanceWrapper);
//進行一些初始化方法的調用,比如afterPropertiesSet等等峭范。
exposedObject?=?initializeBean(beanName,?exposedObject,?mbd);
}
catch(Throwable?ex)?{
if(ex?instanceof?BeanCreationException?&&?beanName.equals(((BeanCreationException)?ex).getBeanName()))?{
throw(BeanCreationException)?ex;
}
}
if(earlySingletonExposure)?{
ObjectearlySingletonReference?=?getSingleton(beanName,false);
if(earlySingletonReference?!=null)?{
if(exposedObject?==?bean)?{
exposedObject?=?earlySingletonReference;
}
//在出現(xiàn)循環(huán)依賴后财松,從earlySingletonObjects中獲取的bean對象和initializeBean后
//的不一致,證明被后置處理器處理過了纱控,前后bean不一致辆毡,需要拋出異常
elseif(!this.allowRawInjectionDespiteWrapping?&&?hasDependentBean(beanName))?{
String[]?dependentBeans?=?getDependentBeans(beanName);
Set?actualDependentBeans?=newLinkedHashSet<>(dependentBeans.length);
for(StringdependentBean?:?dependentBeans)?{
if(!removeSingletonIfCreatedForTypeCheckOnly(dependentBean))?{
actualDependentBeans.add(dependentBean);
}
}
if(!actualDependentBeans.isEmpty())?{
thrownewBeanCurrentlyInCreationException(beanName,
"Bean?with?name?'"+?beanName?+"'?has?been?injected?into?other?beans?["+
StringUtils.collectionToCommaDelimitedString(actualDependentBeans)?+
"]?in?its?raw?version?as?part?of?a?circular?reference,?but?has?eventually?been?"+
"wrapped.?This?means?that?said?other?beans?do?not?use?the?final?version?of?the?"+
"bean.?This?is?often?the?result?of?over-eager?type?matching?-?consider?using?"+
"'getBeanNamesOfType'?with?the?'allowEagerInit'?flag?turned?off,?for?example.");
}
}
}
}
//?注冊bean的銷毀方法
try{
registerDisposableBeanIfNecessary(beanName,?bean,?mbd);
}
catch(BeanDefinitionValidationException?ex)?{
thrownewBeanCreationException(
mbd.getResourceDescription(),?beanName,"Invalid?destruction?signature",?ex);
}
returnexposedObject;
}
doCreateBean大概有以下步驟:
調用createBeanInstance方法初始化bean實例,這里不包括屬性的注入甜害。
調用合并bean的后置處理器修改這個bean的BeanDefinition的一些定義舶掖。即調用MergedBeanDefinitionPostProcessor的實現(xiàn)類的postProcessMergedBeanDefinition方法對BeanDefinition進行一些額外的處理。
為早期的循環(huán)依賴做準備尔店,將包裝了bean的工廠方法塞到singletonFactories中访锻。
調用populateBean方法進行一些屬性的注入。
執(zhí)行initializeBean方法進行一些初始化方法的調用闹获,例如:afterPropertiesSet方法的調用期犬。與此同時,其后置處理器有可能對指定的bean進行增強避诽。
如果出現(xiàn)了bean的增強龟虎,然后又有依賴它的類先生成,則需拋出異常沙庐。例如:對象A被增強了鲤妥,得到A+對象,而此時對象B有依賴對象A拱雏,循環(huán)依賴時通過singletonFactories獲取到的對象卻是增強前的A對象棉安,這時就會出現(xiàn)問題。如果不拋出異常铸抑,spring容器緩存的是A+對象贡耽,但是B引用的卻是A,這樣就會出現(xiàn)不可預測的問題鹊汛。
instantiateBean源碼
這里是createBeanInstance方法中最終調用的方法蒲赂,這里有三個流程:
進行對象的構造,這里關注下CglibSubclassingInstantiationStrategy這個策略類刁憋,有繼承SimpleInstantiationStrategy類滥嘴,調用其instantiate可以調用對象的構造器進行對象的初始化,在BeanDefinition屬性MethodOverrides不存在時至耻,可以用jdk的反射進行獲取對象若皱,否則則必須使用cglib動態(tài)代理镊叁。(這里的MethodOverrides的存在需要對象中某個方法用@Lookup注解修飾,或者XML定義中有 lookup-method屬性
用BeanWrapperImpl對生成的對象進行包裝走触,并激活注冊默認編輯器的屬性晦譬。
注冊默認的編輯器,然后將ConversionService這個類的引用設置到BeanWrapper對象上饺汹。ConversionService是用來進行類型轉換的蛔添,里面的屬性converters用一個map維護著各種類型的轉換器。
populateBean源碼部分
下面關注幾個重點代碼兜辞,省略了一些代碼迎瞧,可以自己去翻閱下:
protectedvoidpopulateBean(String?beanName,?RootBeanDefinition?mbd,?@Nullable?BeanWrapper?bw){
......
PropertyValues?pvs?=?(mbd.hasPropertyValues()???mbd.getPropertyValues()?:null);
if(mbd.getResolvedAutowireMode()?==?AUTOWIRE_BY_NAME?||?mbd.getResolvedAutowireMode()?==?AUTOWIRE_BY_TYPE)?{
MutablePropertyValues?newPvs?=newMutablePropertyValues(pvs);
//?這里是根據bean名稱進行依賴注入的
if(mbd.getResolvedAutowireMode()?==?AUTOWIRE_BY_NAME)?{
autowireByName(beanName,?mbd,?bw,?newPvs);
}
//?這里是根據bean的類型進行依賴注入的
if(mbd.getResolvedAutowireMode()?==?AUTOWIRE_BY_TYPE)?{
autowireByType(beanName,?mbd,?bw,?newPvs);
}
pvs?=?newPvs;
}
......
if(pvs?!=null)?{
//實際上注入屬性值的方法,這里是populateBean方法的重點
applyPropertyValues(beanName,?mbd,?bw,?pvs);
}
}
這里注釋下applyPropertyValues的部分源碼:
protectedvoidapplyPropertyValues(StringbeanName,?BeanDefinition?mbd,?BeanWrapper?bw,?PropertyValues?pvs)?{
MutablePropertyValues?mpvs?=null;
List?original;
if(pvsinstanceofMutablePropertyValues)?{
mpvs?=?(MutablePropertyValues)?pvs;
if(mpvs.isConverted())?{
//?這里可以迅速返回逸吵。當這個PropertyValues對象中的值都是處理過后便可以觸發(fā)凶硅。狀態(tài)值會在下面幾行代碼設置。
try{
bw.setPropertyValues(mpvs);
return;
}
catch(BeansException?ex)?{
thrownewBeanCreationException(
mbd.getResourceDescription(),?beanName,"Error?setting?property?values",?ex);
}
}
original?=?mpvs.getPropertyValueList();
}
else{
original?=?Arrays.asList(pvs.getPropertyValues());
}
TypeConverter?converter?=?getCustomTypeConverter();
if(converter?==null)?{
converter?=?bw;
}
BeanDefinitionValueResolver?valueResolver?=newBeanDefinitionValueResolver(this,?beanName,?mbd,?converter);
//?這里是個深拷貝扫皱,解析所有引用的值足绅。
List?deepCopy?=newArrayList<>(original.size());
boolean?resolveNecessary?=false;
for(PropertyValue?pv?:?original)?{
if(pv.isConverted())?{
deepCopy.add(pv);
}
else{
StringpropertyName?=?pv.getName();
ObjectoriginalValue?=?pv.getValue();
//這里的resolveValueIfNecessary是一個需要關注的方法,有興趣的小伙伴可以點進去看看韩脑,
//里面封裝了針對各種類型的屬性的解析氢妈,例如List,Map,Set等等類型。
ObjectresolvedValue?=?valueResolver.resolveValueIfNecessary(pv,?originalValue);
ObjectconvertedValue?=?resolvedValue;
boolean?convertible?=?bw.isWritableProperty(propertyName)?&&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if(convertible)?{
convertedValue?=?convertForProperty(resolvedValue,?propertyName,?bw,?converter);
}
//為了避免每次創(chuàng)建都去轉換屬性
if(resolvedValue?==?originalValue)?{
//這里的觸發(fā)條件必須為該屬性得是有寫權限的段多,并且里面不能帶有“.”和“[”這個符號首量,這里我的理解是
//teacher.name以及student[1].name這樣的propertyName便不能觸發(fā)這個條件
if(convertible)?{
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
elseif(convertible?&&?originalValueinstanceofTypedStringValue?&&
!((TypedStringValue)?originalValue).isDynamic()?&&
!(convertedValueinstanceofCollection?||?ObjectUtils.isArray(convertedValue)))?{
//這一塊的條件比上一個多了幾個,源值必須是string類型进苍,且不能是動態(tài)的加缘,并且不能是集合和數(shù)組中的任意一個。
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else{
//條件在這里觸發(fā)后就不會打開快捷返回的開關了
resolveNecessary?=true;
deepCopy.add(newPropertyValue(pv,?convertedValue));
}
}
}
//設置converted狀態(tài)值觉啊,供其組裝屬性時快捷返回拣宏。
if(mpvs?!=null&&?!resolveNecessary)?{
mpvs.setConverted();
}
//?將我們深拷貝出來的值設置到包裝類BeanWrapperImpl包裝的對象上
try{
bw.setPropertyValues(newMutablePropertyValues(deepCopy));
}
catch(BeansException?ex)?{
thrownewBeanCreationException(
mbd.getResourceDescription(),?beanName,"Error?setting?property?values",?ex);
}
}
setPropertyValues方法的源碼最終調用的是AbstractNestablePropertyAccessor類的setPropertyValue方法,在這里BeanWrapperImpl是它的實現(xiàn)類杠人,從名字上看也能猜出來這個類是個處理嵌套屬性的訪問器勋乾。
publicvoidsetPropertyValue(String?propertyName,?@Nullable?Objectvalue)?throws?BeansException{
AbstractNestablePropertyAccessor?nestedPa;
try{
//這里可以解析嵌套的屬性
nestedPa?=?getPropertyAccessorForPropertyPath(propertyName);
}
catch(NotReadablePropertyException?ex)?{
thrownewNotWritablePropertyException(getRootClass(),this.nestedPath?+?propertyName,
"Nested?property?in?path?'"+?propertyName?+"'?does?not?exist",?ex);
}
//這里獲取到了最終解析到的屬性名
PropertyTokenHolder?tokens?=?getPropertyNameTokens(getFinalPath(nestedPa,?propertyName));
//給最終解析到的屬性名賦值操作
nestedPa.setPropertyValue(tokens,newPropertyValue(propertyName,value));
}
上面有個getPropertyAccessorForPropertyPath方法,點進去會發(fā)現(xiàn)他會有個解析“.”和“[]”的方法getNestedPropertySeparatorIndex搜吧,它的作用我舉個例子來說明一下:一個班級有多個學生市俊,我想設置某個學生的名字,班級是個Class對象,里面有屬性:private Student[] students這里我想修改下student[2]的name屬性滤奈,我就必須先用getStudent方法取出 Student[] 數(shù)組,然后再在 Student[] 數(shù)組中找到索引為2的Student撩满,最后修改Student身上的name屬性蜒程。
GetBean流程圖
在此我向大家推薦一個架構學習交流群绅你。交流學習群號:938837867 暗號:555 里面會分享一些資深架構師錄制的視頻錄像:有Spring,MyBatis昭躺,Netty源碼分析忌锯,高并發(fā)、高性能领炫、分布式偶垮、微服務架構的原理,JVM性能優(yōu)化帝洪、分布式架構等這些成為架構師必備