5.5 准备创建bean
5.5??準(zhǔn)備創(chuàng)建bean
?
我們不可能指望在一個(gè)函數(shù)中完成一個(gè)復(fù)雜的邏輯,而且我們跟蹤了這么多Spring代碼,經(jīng)歷了這么多函數(shù),或多或少也發(fā)現(xiàn)了一些規(guī)律:一個(gè)真正干活的函數(shù)其實(shí)是以do開頭的,比如doGetObjectFromFactoryBean;而給我們錯(cuò)覺的函數(shù),比如getObjectFromFactoryBean,其實(shí)只是從全局角度去做些統(tǒng)籌的工作。這個(gè)規(guī)則對(duì)于createBean也不例外,那么讓我們看看在createBean函數(shù)中做了哪些準(zhǔn)備工作。
?
1 protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException { 2 3 if (logger.isDebugEnabled()) { 4 logger.debug("Creating instance of bean '" + beanName + "'"); 5 } 6 //鎖定class,根據(jù)設(shè)置的class屬性或者根據(jù)className來(lái)解析Class 7 resolveBeanClass(mbd, beanName); 8 9 //驗(yàn)證及準(zhǔn)備覆蓋的方法 10 try { 11 mbd.prepareMethodOverrides(); 12 } 13 catch (BeanDefinitionValidationException ex) { 14 throw new BeanDefinitionStoreException(mbd.getResourceDescription(), 15 beanName, "Validation of method overrides failed", ex); 16 } 17 18 try { 19 //給BeanPostProcessors一個(gè)機(jī)會(huì)來(lái)返回代理來(lái)替代真正的實(shí)例 20 Object bean = resolveBeforeInstantiation(beanName, mbd); 21 if (bean != null) { 22 return bean; 23 } 24 } 25 catch (Throwable ex) { 26 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 27 "BeanPostProcessor before instantiation of bean failed", ex); 28 } 29 30 Object beanInstance = doCreateBean(beanName, mbd, args); 31 if (logger.isDebugEnabled()) { 32 logger.debug("Finished creating instance of bean '" + beanName + "'"); 33 } 34 return beanInstance; 35 }?
從代碼中我們可以總結(jié)出函數(shù)完成的具體步驟及功能。
(1)根據(jù)設(shè)置的class屬性或者根據(jù)className來(lái)解析Class。
(2)對(duì)override屬性進(jìn)行標(biāo)記及驗(yàn)證。
很多讀者可能會(huì)不知道這個(gè)方法的作用,因?yàn)樵?span style="font-family:'Times New Roman';">Spring的配置里面根本就沒(méi)有諸如override-method之類的配置,那么這個(gè)方法到底是干什么用的呢?
其實(shí)在Spring中確實(shí)沒(méi)有override-method這樣的配置,但是如果讀過(guò)前面的部分,可能會(huì)有所發(fā)現(xiàn),在Spring配置中是存在lookup-method和replace-method的,而這兩個(gè)配置的加載其實(shí)就是將配置統(tǒng)一存放在BeanDefinition中的methodOverrides屬性里,而這個(gè)函數(shù)的操作其實(shí)也就是針對(duì)于這兩個(gè)配置的。
(3)應(yīng)用初始化前的后處理器,解析指定bean是否存在初始化前的短路操作。
(4)創(chuàng)建bean。
我們首先查看下對(duì)override屬性標(biāo)記及驗(yàn)證的邏輯實(shí)現(xiàn)。
?
處理ovverride屬性
?
查看源碼中AbstractBeanDefinition類的prepareMethodOverrides方法:
?
1 public void prepareMethodOverrides() throws BeanDefinitionValidationException { 2 // Check that lookup methods exists. 3 MethodOverrides methodOverrides = getMethodOverrides(); 4 if (!methodOverrides.isEmpty()) { 5 for (MethodOverride mo : methodOverrides.getOverrides()) { 6 prepareMethodOverride(mo); 7 } 8 } 9 } 10 protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException { 11 //獲取對(duì)應(yīng)類中對(duì)應(yīng)方法名的個(gè)數(shù) 12 int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName()); 13 if (count == 0) { 14 throw new BeanDefinitionValidationException( 15 "Invalid method override: no method with name '" + mo.getMethodName() + 16 "' on class [" + getBeanClassName() + "]"); 17 } 18 else if (count == 1) { 19 //標(biāo)記MethodOverride暫未被覆蓋,避免參數(shù)類型檢查的開銷。 20 mo.setOverloaded(false); 21 } 22 }?
通過(guò)以上兩個(gè)函數(shù)的代碼你能體會(huì)到它所要實(shí)現(xiàn)的功能嗎?之前反復(fù)提到過(guò),在Spring配置中存在lookup-method和replace-method兩個(gè)配置功能,而這兩個(gè)配置的加載其實(shí)就是將配置統(tǒng)一存放在BeanDefinition中的methodOverrides屬性里,這兩個(gè)功能實(shí)現(xiàn)原理其實(shí)是在bean實(shí)例化的時(shí)候如果檢測(cè)到存在methodOverrides屬性,會(huì)動(dòng)態(tài)地為當(dāng)前bean生成代理并使用對(duì)應(yīng)的攔截器為bean做增強(qiáng)處理,相關(guān)邏輯實(shí)現(xiàn)在bean的實(shí)例化部分詳細(xì)介紹。
但是,這里要提到的是,對(duì)于方法的匹配來(lái)講,如果一個(gè)類中存在若干個(gè)重載方法,那么,在函數(shù)調(diào)用及增強(qiáng)的時(shí)候還需要根據(jù)參數(shù)類型進(jìn)行匹配,來(lái)最終確認(rèn)當(dāng)前調(diào)用的到底是哪個(gè)函數(shù)。但是,Spring將一部分匹配工作在這里完成了,如果當(dāng)前類中的方法只有一個(gè),那么就設(shè)置重載該方法沒(méi)有被重載,這樣在后續(xù)調(diào)用的時(shí)候便可以直接使用找到的方法,而不需要進(jìn)行方法的參數(shù)匹配驗(yàn)證了,而且還可以提前對(duì)方法存在性進(jìn)行驗(yàn)證,正可謂一箭雙雕。
5.5.2??實(shí)例化的前置處理
在真正調(diào)用doCreate方法創(chuàng)建bean的實(shí)例前使用了這樣一個(gè)方法resolveBeforeInstantiation?(beanName,?mbd)對(duì)BeanDefinigiton中的屬性做些前置處理。當(dāng)然,無(wú)論其中是否有相應(yīng)的邏輯實(shí)現(xiàn)我們都可以理解,因?yàn)檎嬲壿媽?shí)現(xiàn)前后留有處理函數(shù)也是可擴(kuò)展的一種體現(xiàn),但是,這并不是最重要的,在函數(shù)中還提供了一個(gè)短路判斷,這才是最為關(guān)鍵的部分。
?
if (bean != null) {return bean; }?
當(dāng)經(jīng)過(guò)前置處理后返回的結(jié)果如果不為空,那么會(huì)直接略過(guò)后續(xù)的Bean的創(chuàng)建而直接返回結(jié)果。這一特性雖然很容易被忽略,但是卻起著至關(guān)重要的作用,我們熟知的AOP功能就是基于這里的判斷的。
?
1 protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { 2 Object bean = null; 3 //如果尚未被解析 4 if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { 5 // Make sure bean class is actually resolved at this point. 6 if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAware BeanPostProcessors()) { 7 bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName); 8 if (bean != null) { 9 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); 10 } 11 } 12 mbd.beforeInstantiationResolved = (bean != null); 13 } 14 return bean; 15 }?
此方法中最吸引我們的無(wú)疑是兩個(gè)方法applyBeanPostProcessorsBeforeInstantiation以及applyBeanPostProcessorsAfterInitialization。兩個(gè)方法實(shí)現(xiàn)的非常簡(jiǎn)單,無(wú)非是對(duì)后處理器中的所有InstantiationAwareBeanPostProcessor類型的后處理器進(jìn)行postProcessBeforeInstantiation方法和BeanPostProcessor的postProcessAfterInitialization方法的調(diào)用。
1.實(shí)例化前的后處理器應(yīng)用
bean的實(shí)例化前調(diào)用,也就是將AbsractBeanDefinition轉(zhuǎn)換為BeanWrapper?前的處理。給子類一個(gè)修改BeanDefinition的機(jī)會(huì),也就是說(shuō)當(dāng)程序經(jīng)過(guò)這個(gè)方法后,bean可能已經(jīng)不是我們認(rèn)為的bean了,而是或許成為了一個(gè)經(jīng)過(guò)處理的代理bean,可能是通過(guò)cglib生成的,也可能是通過(guò)其它技術(shù)生成的。這在第7章中會(huì)詳細(xì)介紹,我們只需要知道,在bean的實(shí)例化前會(huì)調(diào)用后處理器的方法進(jìn)行處理。
?
1 protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName) 2 throws BeansException { 3 4 for (BeanPostProcessor bp : getBeanPostProcessors()) { 5 if (bp instanceof InstantiationAwareBeanPostProcessor) { 6 InstantiationAwareBeanPostProcessor ibp = (Instantiation AwareBean PostProcessor) bp; 7 Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); 8 if (result != null) { 9 return result; 10 } 11 } 12 } 13 return null; 14 }?
2.實(shí)例化后的后處理器應(yīng)用
在講解從緩存中獲取單例bean的時(shí)候就提到過(guò),Spring中的規(guī)則是在bean的初始化后盡可能保證將注冊(cè)的后處理器的postProcessAfterInitialization方法應(yīng)用到該bean中,因?yàn)槿绻祷氐?/span>bean不為空,那么便不會(huì)再次經(jīng)歷普通bean的創(chuàng)建過(guò)程,所以只能在這里應(yīng)用后處理器的postProcessAfterInitialization方法。
?
1 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) 2 throws BeansException { 3 4 Object result = existingBean; 5 for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { 6 result = beanProcessor.postProcessAfterInitialization(result, beanName); 7 if (result == null) { 8 return result; 9 } 10 } 11 return result; 12 }?
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的5.5 准备创建bean的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 第二次装OA系统
- 下一篇: Java正则表达式获取网页所有网址和链接