在上一篇博客內(nèi)容中,我們已經(jīng)看了解析 import.alias的源碼了,接下來(lái)就是bean的這塊了:
processBeanDefinition(ele, delegate):
從第一個(gè)方法開(kāi)始看過(guò)來(lái),parseBeanDefinitionElement的具體實(shí)現(xiàn):
1.先獲取id與name屬性户誓,將name按照分隔符切割為數(shù)組饼灿,因?yàn)槲覀僴ame可以用逗號(hào)分隔來(lái)指示多個(gè)別名,然后將這個(gè)數(shù)組添加進(jìn)一個(gè)新創(chuàng)建的集合中帝美,如果id屬性為空的話碍彭,創(chuàng)建的name集合又不為空,那么將以第一個(gè)name為這個(gè)bean的id
2.checkNameUniqueness(beanName.aloases,ele):該方法的目的是校驗(yàn)這個(gè)id悼潭,是否存在所有的bean的id集合中庇忌,該集合為一個(gè)Set集合,因?yàn)橐WCid的強(qiáng)一致性(即使A bean的id 與B bean 的name有相同也是不行的舰褪,因?yàn)閎ean的name屬性也會(huì)被添加進(jìn)這個(gè)集合中皆疹,如果有定義了多個(gè)name,那么第一個(gè)值占拍,必須是唯一的略就,如果在name的數(shù)組中還找到了相同的,同樣會(huì)提示Error)
接著上圖往下看:
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean):?解析bean定義本身晃酒,而不考慮名稱或別名
AbstractBeanDefinition :具體的BeanDefinition類的基類表牢,分解出GenericBeanDefinition,RootBeanDefinition和ChildBeanDefinition的公共屬性
this.parseState =?ParseState對(duì)象
ParseState:基于簡(jiǎn)單LinkedList的結(jié)構(gòu),用于跟蹤解析過(guò)程中的邏輯位置
Entry:在解析階段的每一點(diǎn)都以特定于讀取器的方式添加到LinkedList中贝次。用于ParseState條目的標(biāo)記接口
BeanEntry:表示bean定義的ParseState條目
接下來(lái)來(lái)看第二部分:
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;? ?(這里是補(bǔ)充)
這里我們來(lái)詳細(xì)看下怎么設(shè)置property屬性的吧,其他的地方都比較簡(jiǎn)單敲茄,property屬性我們也使用的最多了螺戳,所以看下實(shí)現(xiàn)原理也是有必要滴
parsePropertyElements(ele, bd):
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
????????NodeList nl = beanEle.getChildNodes();
????????for (int i = 0; i < nl.getLength(); i++) {
????????????????????Node node = nl.item(i);
????????????????????if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) { //property
????????????????????????????parsePropertyElement((Element) node, bd);
????????????????????}
????????}
}
如果是property標(biāo)簽則進(jìn)入parsePropertyElement方法:
public void parsePropertyElement(Element ele, BeanDefinition bd) {
? ? ? ? ? ?String propertyName = ele.getAttribute(NAME_ATTRIBUTE); // name
? ? ? ? ? ?if (!StringUtils.hasLength(propertyName)) {
????????????????????error("Tag 'property' must have a 'name' attribute", ele);
????????????????????return;
????????????}
? ? ? ? ? ? // 添加propertyName條目
????????????this.parseState.push(new PropertyEntry(propertyName));
????????????try {
????????????????????????//校驗(yàn)該peoperty是否已存在
????????????????????????if (bd.getPropertyValues().contains(propertyName)) {
????????????????????????????????error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
????????????????????????????????return;
????????????????????????}
? ? ? ? ? ? ? ? ? ? ? ? //?獲取屬性元素的值 (具體怎么做的在下面可以看得到)
????????????????????????Object val = parsePropertyValue(ele, bd, propertyName);
? ? ? ? ? ? ? ? ? ? ? ?// 屬性值對(duì)象?
????????????????????????PropertyValue pv = new PropertyValue(propertyName, val);
? ? ? ? ? ? ? ? ? ? ? ?// 判斷是否存在meta標(biāo)簽,有則設(shè)置進(jìn)pv中折汞,因?yàn)槲覀冊(cè)趯懪渲梦募臅r(shí)候其實(shí)是可以往property標(biāo)簽中插入meta標(biāo)簽的
????????????????????????parseMetaElements(ele, pv);
? ? ? ? ? ? ? ? ? ? ? ? // 這里啥也沒(méi)干
????????????????????????pv.setSource(extractSource(ele));
? ? ? ? ? ? ? ? ? ? ? ? // 添加進(jìn)BeanDefinition中
????????????????????????bd.getPropertyValues().addPropertyValue(pv);
????????????} finally {
? ? ? ? ? ? ? ? ? ? ? ? // 這里就不用說(shuō)了,要不然就顯得太羅嗦了
????????????????????????this.parseState.pop();
????????????}
}
Object val = parsePropertyValue(ele, bd, propertyName):獲取屬性值
1.首先是property的子元素是否只有一個(gè)
2.直接貼代碼
boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);? ? ? ? ? ? ? ? ? ? ?//ref
boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);???????????? //value
// ref和value屬性不能一起出現(xiàn)在一個(gè)property標(biāo)簽中
if ((hasRefAttribute && hasValueAttribute) || ((hasRefAttribute || hasValueAttribute) && subElement != null)) {
????????error(elementName + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
}
if (hasRefAttribute) {
????????String refName = ele.getAttribute(REF_ATTRIBUTE);
????????if (!StringUtils.hasText(refName)) {
????????????????error(elementName + " contains empty 'ref' attribute", ele);
????????}
? ? ? ? //?RuntimeBeanReference? :不可變占位符類盖腿,當(dāng)屬性值對(duì)象引用工廠中的另一個(gè)bean時(shí)爽待,用于在運(yùn)行時(shí)解析它
? ? ? ?RuntimeBeanReference ref = new RuntimeBeanReference(refName);
? ? ? ?// 啥也不干?
? ? ? ?ref.setSource(extractSource(ele));
? ? ? ?return ref;
?}else if (hasValueAttribute) {
? ? ? ? //?TypedStringValue:Spring類型字符串值的Holder◆娓可以添加到bean定義中鸟款,以便顯式地指定字符串值的目標(biāo)類型,例如集合元素
? ? ? ? //?這個(gè)holder只存儲(chǔ)字符串值和目標(biāo)類型茂卦。實(shí)際的轉(zhuǎn)換將由bean工廠執(zhí)行何什。
????????TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
? ? ? ? // 這里也是啥都不干
????????valueHolder.setSource(extractSource(ele));
????????return valueHolder;
}
PropertyValue:對(duì)象來(lái)保存單個(gè)bean屬性的信息和值。在這里使用一個(gè)對(duì)象等龙,而不是僅僅將所有屬性存儲(chǔ)在一個(gè)按屬性名鍵控的映射中处渣, 這允許更大的靈活性,以及以優(yōu)化的方式處理索引屬性等蛛砰。
MutablePropertyValues:PropertyValues接口的默認(rèn)實(shí)現(xiàn),允許對(duì)屬性進(jìn)行簡(jiǎn)單的操作罐栈,并提供構(gòu)造函數(shù)來(lái)支持映射的深度復(fù)制和構(gòu)造。
然后就沒(méi)有然后了泥畅。就直接返回了荠诬,再回到parseBeanDefinitionElement方法中可以發(fā)現(xiàn),下面還有一些對(duì)于bean的id為空的情況下的處理位仁,這里我就不說(shuō)了(時(shí)間原因柑贞,其實(shí)看源碼看到這里,接下來(lái)的東西也就沒(méi)啥難度了)
那么就回到parseBeanDefinitionElement方法的最后這一點(diǎn) :
String[] aliasesArray = StringUtils.toStringArray(aliases);? ? ? ? ? ? ? ?
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
BeanDefinitionHolder:包含名稱和別名的bean定義的Holder聂抢【唬可以注冊(cè)為內(nèi)部bean的占位符。注冊(cè)RootBeanDefinition或ChildBeanDefinition就足夠了
最后返回的是BeanDefinitionHolder對(duì)象.
這里習(xí)慣性做個(gè)總結(jié)吧:
1.如果name屬性為空涛浙,別名集合不為空康辑,那么將以第一個(gè)別名設(shè)置為該bean的id
2.驗(yàn)證指定的bean名稱和別名在當(dāng)前bean元素嵌套級(jí)別中尚未使用
3.創(chuàng)建GenericBeanDefinition,并且為 GenericBeanDefinition 設(shè)置parentName轿亮,className
4.設(shè)置前置屬性(singleton疮薇,scope,abstract我注,default-lazy-init按咒,autowire,depend-on,autowire-candidate,primary励七,init-method智袭,destroy-method...)
5.判斷是否有description標(biāo)簽,如果有則返回
6.判斷是否是meta標(biāo)簽,如果存在設(shè)置進(jìn)BeanDefintion
7.判斷是否是lookup-method標(biāo)簽,如果存在則添加進(jìn)覆蓋方法列表
8.判斷是否是replaced-method標(biāo)簽,如果存在則添加進(jìn)替換方法列表
9.解析給定bean元素的構(gòu)造 constructor-arg子元素
10.解析屬性元素
11:解析qualifier元素?????
12:設(shè)置source為XmlBeanDefinitionReader
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//BeanDefinitionHolder :包含名稱和別名的bean定義的Holder掠抬『鹨埃可以注冊(cè)為內(nèi)部bean的占位符。
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);? ? ? ? ? ? // 這里咱們就看完了两波,接著往下看
????????if (bdHolder != null) {
? ? ? ? ? ? ? ? // 解析我們自定義的屬性
????????????????bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
????????????????try {
????????????????????????// Register the final decorated instance. // 注冊(cè)最后修飾后的實(shí)例瞳步。
????????????????????????BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
? ? ? ? ? ? ? ? } catch (BeanDefinitionStoreException ex) {
????????????????????????getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex);
????????????????}
????????????????// Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
????????}
}
???bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder):
public BeanDefinitionHolder decorateBeanDefinitionIfRequired( Element ele, BeanDefinitionHolder definitionHolder, @Nullable BeanDefinition containingBd) {
????????BeanDefinitionHolder finalDefinition = definitionHolder;
????????// 首先基于自定義屬性進(jìn)行裝飾
????????NamedNodeMap attributes = ele.getAttributes();
????????for (int i = 0; i < attributes.getLength(); i++) {
????????????????Node node = attributes.item(i);
????????????????finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
????????}
????????// 基于自定義嵌套元素的裝飾
????????NodeList children = ele.getChildNodes();
????????for (int i = 0; i < children.getLength(); i++) {
????????????????Node node = children.item(i);
????????????????if (node.getNodeType() == Node.ELEMENT_NODE) {
????????????????????????finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
????????????????}
????????}
????????return finalDefinition;
}
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()) : 注冊(cè)最后修飾后的實(shí)例,將給定的bean定義注冊(cè)到給定的bean工廠
getReaderContext().getRegistry()? 等同于 XmlBeanDefinitionReader.getRegistry() 返回DefaultListableBeanFactory
public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
????????// Register bean definition under primary name.
????????String beanName = definitionHolder.getBeanName();
????????registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());? ? ? ? ? ? ? ? // 我們主要來(lái)看看這個(gè)方法是怎么實(shí)現(xiàn)的
????????// Register aliases for bean name, if any.
????????String[] aliases = definitionHolder.getAliases();
????????if (aliases != null) {
????????????????for (String alias : aliases){
????????????????????registry.registerAlias(beanName, alias);
????????????????}
????????}
}
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()):
1.首先是對(duì)beanDefinition進(jìn)行校驗(yàn)(存在覆蓋方法并且工廠方法不為空(創(chuàng)建該Bean的工廠方法就不能被覆蓋,校驗(yàn)該beanClass是否為Class實(shí)例)
2.然后在BeanDefinition緩存中找,目的是為了知道該beanName的beanDefinition是否已經(jīng)存在劣坊,如果存在做另外一種處理嘀倒,這里我們就不看了
3.判斷該beanName是否已經(jīng)創(chuàng)建過(guò)(AbstractBeanFactory中的alreadyCreated:至少創(chuàng)建過(guò)一次的bean的名稱),如果不為空的話局冰,首先是先把咱們的beanName與BeanDefinition添加進(jìn) beanName -> BeanDefinition的緩存中测蘑,然后從新初始化bean定義名稱列表(beanDefinitionNames集合,也是DefaultListableBeanFactory中的屬性康二,一個(gè)List集合)帮寻,初始化的目的就是為了將我們的beanName添加進(jìn)集合中,接著如果beanName存在與手動(dòng)注冊(cè)的單例程序的名稱列表(DefaultListableBeanFactoty中的屬性赠摇,一個(gè)Set集合)中的話固逗,也是從新初始化該集合,不同的是這里是從集合中刪除該beanName(如果是存在集合中的話), 初始化(copy-on-write)
4.那就是第三步的else部分了藕帜,這里比第三步就直接多了烫罩,beanName與BeanDefinition添加進(jìn) beanName -> BeanDefinition的緩存中,beanName添加進(jìn)bean定義名稱列表洽故,刪除手動(dòng)注冊(cè)的單例程序的名稱列表中的該beanName
5.最后一步贝攒,判斷beanDefintion是否存在或者是否已經(jīng)存在與我們的緩存映射中,如果滿足條件則開(kāi)始清理时甚,我們來(lái)把清理的過(guò)程和內(nèi)容記錄一下
1.緩存對(duì)象的bean的名字:bean名稱到bean實(shí)例中刪除beanName???????????????????????????????DefaultSingletonBeanRegistry.singletonObjects
2.單例工廠的緩存:對(duì)象工廠的bean名稱中刪除beanName???????????????????????????????????????????DefaultSingletonBeanRegistry.singletonFactories??????
3.早期:?jiǎn)卫龑?duì)象緩存的bean bean實(shí)例的名字中刪除beanName? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DefaultSingletonBeanRegistry.earlySingletonObjects? ??
4.注冊(cè)的單例集合隘弊,按注冊(cè)順序包含bean名稱中刪除beanName????????????????????????????????????DefaultSingletonBeanRegistry.registeredSingletons
5.手動(dòng)注冊(cè)的單例程序的名稱列表,按注冊(cè)順序排列(再特么刪一次)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DefaultListableBeanFactory.manualSingletonNames
6.清空單例和非單例bean名稱的映射荒适,按依賴項(xiàng)類型鍵控? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DefaultListableBeanFactory.allBeanNamesByType? ? ? ? ?
7.清空單一bean名稱的映射梨熙,按依賴項(xiàng)類型鍵控? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??DefaultListableBeanFactory.singletonBeanNamesByType
到這里registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())就已經(jīng)結(jié)束了,這一步的話其實(shí)主要就是將beanName與創(chuàng)建好的BeanDefinition放在緩存中管理起來(lái)刀诬,回到registerBeanDefinition方法中我們繼續(xù)往下看
//? ?為bean名稱注冊(cè)別名(如果有的話)?
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
? ??for (String alias : aliases) {
? ??????registry.registerAlias(beanName, alias);
? ? }
}
registry.registerAlias(beanName, alias): 這個(gè)地方我就直接把代碼貼上這樣方便看咽扇,內(nèi)容也挺簡(jiǎn)單的,所以就不記錄下來(lái)了
public void registerAlias(String name, String alias) {
????????Assert.hasText(name, "'name' must not be empty");
????????Assert.hasText(alias, "'alias' must not be empty");
? ??????synchronized (this.aliasMap) {
? ??????????????if (alias.equals(name)) {
? ??????????????????????this.aliasMap.remove(alias);
? ??????????????????????if (logger.isDebugEnabled()) {
? ??????????????????????????????????logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ?}else{
? ? ? ? ? ? ? ? ? ? ? ??String registeredName = this.aliasMap.get(alias);
? ??????????????????????if (registeredName != null) {
? ??????????????????????????????if (registeredName.equals(name)) {
? ??????????????????????????????????????return;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ??????????????????????????????if (!allowAliasOverriding()) { // 是否允許別名覆蓋。默認(rèn)值是true;
? ??????????????????????????????????????throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" + name + "': It is already registered for ????????????????????????????????????????name '" + registeredName + "'.");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ??????????????????????????????if (logger.isDebugEnabled()) {
? ??????????????????????????????????????logger.debug("Overriding alias '" + alias + "' definition for registered name '" + registeredName + "' with new target name ????????????????????????????????????????????'" + name + "'");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? }
? ??????????????????????checkForAliasCircle(name, alias); // 檢查給定名稱是否已經(jīng)指向另一個(gè)方向的給定別名作為別名
? ??????????????????????this.aliasMap.put(alias, name); // 添加進(jìn)id與alias的映射
? ??????????????????????if (logger.isTraceEnabled()) {
? ??????????????????????????????logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
? ? ? ? ? ? ? ? ? ? ? ? }
????????????????}
? ? ? ? }
}
ok了质欲,BeanDefintion跟Aliases都注冊(cè)了树埠,那么registerBeanDefinition這個(gè)方法就完了,就是這樣啦嘶伟,哈哈哈哈怎憋,不管里頭有多復(fù)雜,反正就是特么的兩件事九昧,注冊(cè)我們根據(jù)<bean> 創(chuàng)建的BeanDefintion,注冊(cè)該Bean的別名
那我們?cè)倩氐絧rocessBeanDefinition方法中盛霎,還有最后一個(gè)方法:,其實(shí)最后這個(gè)地方都可以不用說(shuō)了,因?yàn)檫@里其實(shí)也還是啥都沒(méi)干(反正調(diào)ReaderContext中那三個(gè)屬性的方法都是沒(méi)干活的耽装,哈哈哈哈哈)
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder))?
那這里就完了.....就沒(méi)了期揪,真的沒(méi)了掉奄,然后我們?cè)倩氐阶畛醯膁oRegisterBeanDefinitions方法中,我們?cè)倏纯磒arseBeanDefinitions(root, this.delegate);下面還有沒(méi)有其他的方法需要進(jìn)去看看
parseBeanDefinitions(root, this.delegate);? ? ? ? ? ? ? ? //這個(gè)已經(jīng)看完了
postProcessXml(root);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 這里不用看凤薛,因?yàn)橄旅娴膶?shí)現(xiàn)是空的
this.delegate = parent;
this.delegate = parent: 這里我想我大概弄懂為啥要這樣子再賦值一下的意義了姓建,在進(jìn)入方法的第一步時(shí)就把這個(gè)delegate 賦值給了parent對(duì)象,最后再賦值回來(lái)缤苫,這說(shuō)明它想保存當(dāng)時(shí)的狀態(tài)速兔,但是為啥要這樣子搞,我還不清楚
回到parseDefaultElement方法中活玲,目前我們已經(jīng)把解析import涣狗,alias,bean都說(shuō)了舒憾,還有最后一個(gè)
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)){
????// 檢查節(jié)點(diǎn)名稱是否等于beans // recurse
????doRegisterBeanDefinitions(ele);
}
這就不用看了镀钓,因?yàn)檫€不是回著頭再搞一次,我們本來(lái)就是通過(guò)doRegisterBeanDefinitions方法進(jìn)入的嘛 ==
接著再回到AbstractRefreshableApplicationContext:
再回到這個(gè)最初的方法:
這個(gè)地方那就是返回我們上面創(chuàng)建的DefaultListableBeanFactory了?
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 到這里這個(gè)方法就算是結(jié)束了,做個(gè)總結(jié):
1.new??DefaultListableBeanFactory,AbstractBeanFactory中設(shè)置parentBeanFactory為ApplicationContext,factoryBean設(shè)置唯一標(biāo)識(shí)
2.對(duì)ioc容器進(jìn)行定制化丁溅,如設(shè)置啟動(dòng)參數(shù),開(kāi)啟注解的自動(dòng)裝配等
3.解析<bean>并且注冊(cè)BeanDefinition
4.AbstractAutowireCapableBeanFactory的忽略依賴關(guān)系接口集合屬性中添加了 BeanNameAware,BeanFactoryAware探遵,BeanClassLoaderAware
5.AbstractBeanDefinitionReader中設(shè)置resourceLoader 為PathMatchingResourcePatternResolver
6.AbstractBeanDefinitionReader中設(shè)置environment 為StandardEnvironment
7.設(shè)置XmlBeanDefinitionReader的Environment屬性為AbstractApplicationContext中的StandardEnvironment (在我們之前super(parent)這一步的時(shí)候給new的)
8.設(shè)置XmlBeanDefinitionReader的ResourceLoader為AbstractXmlApplicationContext
9.設(shè)置XmlBeanDefinitionReader的EntityResolver為ResourceEntityResolver
10.設(shè)置AbstractRefreshableApplicationContext的beanFactory屬性為DefaultListableBeanFactory
11.返回DefaultListableBeanFactory
3.prepareBeanFactory(beanFactory):
一個(gè)一個(gè)來(lái)窟赏,先從第一個(gè)開(kāi)始
這里我們應(yīng)該是沒(méi)有給DefaultResourcceLoader設(shè)置過(guò)屬性的(反正我印象中是沒(méi)有 ==),那我們就直接看ClassUtils.getDefaultClassLoader()這個(gè)方法吧
這個(gè)方法很簡(jiǎn)單吧箱季,先記起來(lái)這里是從當(dāng)前線程中獲取classLoader
? ?下一步 :beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
先來(lái)說(shuō)說(shuō)這兩個(gè)類是啥類:
StandardBeanExpressionResolver:BeanExpressionResolver?接口的標(biāo)準(zhǔn)實(shí)現(xiàn)涯穷,?使用Spring的表達(dá)式模塊解析和評(píng)估Spring EL
SpelParserConfiguration :?SpEL表達(dá)式解析器的配置對(duì)象
SpelExpressionParser :?SpEL 分析器。實(shí)例是可重用和線程安全的藏雏。
其實(shí)這種我們?cè)谥暗牟襟E中也有類似的求豫,只不過(guò)在處理這塊沒(méi)這么高大上而已,哈哈哈哈,這里我就不細(xì)說(shuō)是哪個(gè)地方了蝠嘉,大家可以自己再?gòu)念^對(duì)著源碼看一遍? >_<
我們來(lái)寫個(gè)Demo看看這到底是干嘛的吧最疆,光說(shuō)的話太不清晰了
有意思的事情就這么發(fā)生了
這個(gè)可能還不怎么明顯,我們?cè)賮?lái)一種玩法
注意配置文件給換了哦~
我再把這個(gè)User類給貼上就知道啥意思了 ==?
這下子清晰了吧 == !
我就不介紹太多了蚤告,給大家推薦兩個(gè)地址吧努酸,哈哈哈
http://www.cnblogs.com/longronglang/p/6180023.html? ? ??
https://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/expressions.html
下一個(gè):
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));? ?//屬性編輯器
自定義屬性編輯器或注冊(cè)表以應(yīng)用于此工廠的bean。
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)):
ApplicationContextAwareProcessor:該類是BeanPostProcessor接口的實(shí)現(xiàn)它是用來(lái)處理和回調(diào)Aware接口的Bean杜恰,不知道大家有沒(méi)有這樣子使用過(guò):
寫一個(gè)接口繼承ApplicationContextAware接口获诈,重寫setApplicationContext方法,然后某個(gè)實(shí)現(xiàn)類心褐,就可以獲取到ApplicationContext對(duì)象舔涎,具體怎么玩,我們還是來(lái)寫個(gè)Demo吧
寫個(gè)測(cè)試接口繼承ApplicationContextAware接口
吶~就是這樣了
我們來(lái)看看這個(gè)方法里頭是怎么做的:
考慮到安全問(wèn)題逗爹,所以直接是使用CopyOnWriteArrayList這個(gè)對(duì)象 (不得不說(shuō)看Spring源碼亡嫌,真的是學(xué)到了很多東西)
CopyOnWriteArrayList這個(gè)類的介紹給大家推薦一個(gè)很不錯(cuò)的地方去看:http://ifeve.com/java-copy-on-write/
1.首先是從集合中刪除掉這個(gè)對(duì)象,這里要說(shuō)一點(diǎn)注意的就是后置處理器是按照注冊(cè)的順序提交的掘而,所以添加的這個(gè)元素得是唯一的
2.判斷是否是InstantiationAwareBeanPostProcessor接口的實(shí)例(InstantiationAwareBeanPostPressor接口可以返回代理對(duì)象挟冠,例如在創(chuàng)建Bean時(shí),并不都是通過(guò)反射來(lái)為我們的bean來(lái)直接new一個(gè)對(duì)象的袍睡,很多時(shí)候都是通過(guò)cglib來(lái)生成一個(gè)代理類知染,這樣做的好處就是更方便Spring來(lái)管理這些Bean,例如在Aop的時(shí)候斑胜,代理類就發(fā)揮了很大的作用控淡,這里我們先不細(xì)講,到后面自然就明白了),我們?cè)谶@里穿的是一個(gè)ApplicationContextAwareProcessor對(duì)象止潘,所以這里不管
3.判斷是否是DestructionAwareBeanPostProcessor接口的實(shí)例逸寓,這里也不管,因?yàn)檫@里也是走false(eanPostProcessor的子接口覆山,它添加了一個(gè)before-destruction回調(diào),銷毀bean后置處理器)
4.最后把穿入的beanPostProcessor添加進(jìn)后置處理器集合中竹伸。
來(lái)簡(jiǎn)單看看這個(gè)BeanPostProcessor接口吧,看看實(shí)現(xiàn)它的作用在哪里.
BeanPostProcessor :
ApplicationContext會(huì)自動(dòng)找到我們實(shí)現(xiàn)了BeanPostProcessor接口的所有類簇宽,然后把這些類都注冊(cè)為后置處理器
先貼一張圖 == (我寫的這篇可能圖片勋篓,代碼貼的比較多,可能不符合很多人的閱讀習(xí)慣魏割,這里先說(shuō)聲不好意思了譬嚣,因?yàn)槲矣X(jué)得貼圖比較親切 ==。)
直接來(lái)寫個(gè)Demo看看這個(gè)實(shí)現(xiàn)了這個(gè)接口到底能干嘛吧 ==?
這里我可是給user設(shè)置了name的
這里我可沒(méi)有設(shè)置喲? =_=
吶钞它,就是這樣
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
這里大家應(yīng)該不陌生拜银,因?yàn)樵诳磑btainFreshBeanFactory()該方法的源碼時(shí)殊鞭,也做過(guò)這種事情 == ,就是往AbstractAutowireCapableBeanFactory中的ignoreDependencyInterfaces Set集合中添加忽略依賴關(guān)系類型
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this):
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this):
beanFactory.registerResolvableDependency(ApplicationContext.class, this):
注冊(cè)具有相應(yīng)自動(dòng)獲取值的特殊依賴項(xiàng)類型,添加進(jìn)Default'List'ableBeanFactory的resolvableDependencies集合中
先記下這里是干了這件事
來(lái)看看DefaultListableBeanFactory的體系吧
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)):
檢測(cè)實(shí)現(xiàn)ApplicationListener接口的bean
接著往下:
老規(guī)矩一個(gè)方法一個(gè)個(gè)來(lái)
先從transformedBeanName(name);這個(gè)方法開(kāi)始
判斷我們傳遞的name是不是以“&”開(kāi)頭的尼桶,要是的需要去掉再返回 操灿,另外我們?cè)谂渲肂ean時(shí),我們是可以配置這個(gè)bean的name屬性的也就是這個(gè)Bean的別名泵督,在canonicalName方法中趾盐,我么就是通過(guò)別名來(lái)找到這個(gè)bean的ID,下面就會(huì)說(shuō)到為啥要獲取到Bean 的ID
if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
}
1.首先是在DefaultSingletonBeanRegistry中判斷該name是否存在singletonObjects Map屬性中(singletonObjects: 緩存對(duì)象的bean的名字:bean名稱到bean實(shí)例)
2.containsBeanDefinition該方法是一個(gè)抽象方法小腊,在子類DefaultListableBeanFactory中可以找到該方法實(shí)現(xiàn)救鲤,該判斷是判斷在DefaultListableBeanFactory的be'an'DefinitionMap屬性中是否存在(beanDefinitionMap: beanName與BeanDefinition對(duì)象的映射)
BeanFactory parentBeanFactory = getParentBeanFactory();
return (parentBeanFactory !=null && parentBeanFactory.containsBean(originalBeanName(name)));
我們?cè)诳磑btainFreshBeanFactory()方法的源碼時(shí),在實(shí)現(xiàn)中已經(jīng)給AbstractBeanFactory的parentBeanFactory屬性設(shè)置了值秩冈,而這個(gè)值就是一開(kāi)始我們傳入的ApplicationContext,但是ApplicationContext并沒(méi)有賦值本缠,所以它依然還是null,那么這個(gè)方法的返回就是false
總結(jié):?beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME) :?檢測(cè) loadTimeWeaver是否存在bean實(shí)例或BeanDefinition對(duì)象
下一個(gè):
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
????????beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
transformedBeanName這個(gè)方法上面已經(jīng)說(shuō)了入问,就不重復(fù)了丹锹,就直接看看下面是干嘛的吧
(containsSingleton(beanName) || containsBeanDefinition(beanName)) &&
(!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName))
這里也是直接走的false因?yàn)槌跏蓟瘯r(shí)這個(gè)bean是既沒(méi)有實(shí)例也沒(méi)有BeanDefinition的,所以這里我們就快速走完吧队他,其他的也不細(xì)講了,等源碼看到一定程度后峻村,再回過(guò)頭來(lái)把這些看一下寫一下麸折,效果可能會(huì)更好一點(diǎn)(其實(shí)我壓根沒(méi)看過(guò)這里的代碼),既然上面已經(jīng)走完了粘昨,但是我們?cè)跅l件里取反垢啼,所以來(lái)看看如果不存在的情況下是對(duì)這個(gè)Bean做了什么處理吧
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
直接貼實(shí)現(xiàn),哈哈哈哈张肾,我越來(lái)越愛(ài)直接貼了
這里顯示判斷是否存在該bean 的實(shí)例芭析,不存在則添加,存在則報(bào)錯(cuò)吞瞪,單例嘛
那我們?cè)賮?lái)看看這個(gè)添加的方法
1.該bean添加實(shí)例
2. 刪除該Bean對(duì)應(yīng)的對(duì)象工廠
3.刪除該Bean的早期單例對(duì)象
4.添加進(jìn)注冊(cè)的Bean集合
這里我們來(lái)看看假如這里不是空的會(huì)發(fā)生什么:
synchronized (this.beanDefinitionMap) {
if (!this.beanDefinitionMap.containsKey(beanName)) {
? ? ? ?Set updatedSingletons =new LinkedHashSet<>(this.manualSingletonNames.size() +1);? ?
? ? ? updatedSingletons.addAll(this.manualSingletonNames);
? ? ? updatedSingletons.add(beanName);
? ? ? this.manualSingletonNames = updatedSingletons;
? }
}else {
? ?if (!this.beanDefinitionMap.containsKey(beanName)) {
????????????this.manualSingletonNames.add(beanName);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 手動(dòng)注冊(cè)的單例程序的名稱列表
? ? ?}
}
最后還有一個(gè)clearByTypeCache()
getEnvironment()這個(gè)就不用說(shuō)了吧馁启,不用想也知道這是什么飛機(jī),我們最開(kāi)始就new了一個(gè)StandardEnvironment == 芍秆,下面兩個(gè)也不說(shuō)了惯疙,其實(shí)都一樣了(夜深了,該睡了 == )
到這里prepareBeanFactory方法就算是完了妖啥,我們來(lái)總結(jié)一下吧:
1.從當(dāng)前Thread中獲取類加載器并且設(shè)置進(jìn)beanFactory
2.設(shè)置表達(dá)式的解析策略
3.設(shè)置屬性編輯器
4.設(shè)置后置處理器
5.添加忽略自動(dòng)連接的給定依賴接口
6.從依賴項(xiàng)類型映射到相應(yīng)的對(duì)象
????????????BeanFactory -> DefaultListableBeanFactory
????????????ResourceLoader -> AbstractApplicationContext
????????????ApplicationEventPublisher -> AbstractApplicationContext
????????????ApplicationContext -> AbstractApplicationContext
7.檢測(cè)實(shí)現(xiàn)ApplicationListener接口的bean
8.檢測(cè) loadTimeWeaver是否存在bean實(shí)例或BeanDefinition對(duì)象? ??
9.檢測(cè)是否存在 environment/systemProperties/systemEnvironment??的Bean實(shí)例與BeanDefinition對(duì)象,不存在則添加
還有這么多沒(méi)寫 == 臥槽
感覺(jué)已經(jīng)寫的很多很羅嗦了霉颠,還是不要都寫一塊比較好,不過(guò)我會(huì)盡快把剩下的寫完的荆虱,哈哈哈哈蒿偎,感謝大家的閱覽朽们!(不早了朦蕴,該睡了躏结,明天還得上班呢嘉裤,晚安)
包含名稱和別名的bean定義的Holder茬底∏澹可以注冊(cè)為內(nèi)部bean的占位符马昨。