概述
前面我們介紹了BeanDefinition的載入和解析的過(guò)程,將我們定義好的Bean資源文件載入并轉(zhuǎn)換成了Document對(duì)象迫像,然后Document對(duì)象通過(guò)BeanDefinitionDocumentReader來(lái)解析在旱,這些動(dòng)作完成以后貌矿,用戶自定義的BeanDefinition信息已經(jīng)在IOC容器內(nèi)建立起了自己的數(shù)據(jù)結(jié)構(gòu)雷蹂,以及相應(yīng)的數(shù)據(jù)表示姆怪,但這些數(shù)據(jù)還不能在IOC容器中直接使用也物,需要在IOC容器中對(duì)這些BeanDefinition進(jìn)行注冊(cè)宫屠。這個(gè)注冊(cè)為IOC容器提供了更友好的使用方式。在DefaultListableBeanDactory
中是使用一個(gè)Map對(duì)象載入并持有這些BeanDefinition
的滑蚯,代碼如下所示:
/** Map of bean definition objects, keyed by bean name. */
/**持有BeanDefinition的map容器**/
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
源碼解析
1.核心流程時(shí)序圖:
從源碼實(shí)現(xiàn)的角度我們可以分析得到上圖的調(diào)用關(guān)系浪蹂。我們可以跟蹤源碼具體看一下注冊(cè)實(shí)現(xiàn)抵栈,在
DefaultListableBeanFactory
中實(shí)現(xiàn)了BeanDefinitionRegistry
的接口,這個(gè)接口的實(shí)現(xiàn)完成了BeanDefinition
向容器注冊(cè)坤次。注冊(cè)過(guò)程就是將解析得到的BeanDefinition
設(shè)置到Map中去古劲,但是如果遇到同名的BeanDefinition
,進(jìn)行處理的時(shí)候需要依據(jù)allowBeanDefinitionOverriding
的配置來(lái)完成缰猴。下面我們就BeanDefinition
的注冊(cè)邏輯展開(kāi)分析产艾。
2.源代碼分析
-
registerBeanDefinitions核心流程代碼解析:
/** * 通過(guò)解析Document解析注冊(cè)BeanDefinition * Register the bean definitions contained in the given DOM document. * Called by {@code loadBeanDefinitions}. * <p>Creates a new instance of the parser class and invokes * {@code registerBeanDefinitions} on it. * @param doc the DOM document * @param resource the resource descriptor (for context information) * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of parsing errors * @see #loadBeanDefinitions * @see #setDocumentReaderClass * @see BeanDefinitionDocumentReader#registerBeanDefinitions */ public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { // 獲取BeanDefinition的Document解析器 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); // 獲取已經(jīng)注冊(cè)的BeanDefinition的個(gè)數(shù) int countBefore = getRegistry().getBeanDefinitionCount(); // 創(chuàng)建XmlRederContext,解析Document并注冊(cè)BeanDefinition documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); // 計(jì)算新注冊(cè)的BeanDefinition的數(shù)量 return getRegistry().getBeanDefinitionCount() - countBefore; }
-
registerBeanDefinitions的處理邏輯解析:
/** * This implementation parses bean definitions according to the "spring-beans" XSD (or DTD, historically). * document中element的解析并注冊(cè)BeanDefinition· * <p>Opens a DOM Document; then initializes the default settings * specified at the {@code <beans/>} level; then parses the contained bean definitions. */ @Override public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; doRegisterBeanDefinitions(doc.getDocumentElement()); }
-
doRegisterBeanDefinitions處理邏輯解析
/** * Register each bean definition within the given root {@code <beans/>} element. */ @SuppressWarnings("deprecation") // for Environment.acceptsProfiles(String...) protected void doRegisterBeanDefinitions(Element root) { // Any nested <beans> elements will cause recursion in this method. In // 從<beans />配置中注冊(cè)每一個(gè)bean滑绒,如果有嵌套的beans闷堡,那么遞歸執(zhí)行這個(gè)方法。 // order to propagate and preserve <beans> default-* attributes correctly, // keep track of the current (parent) delegate, which may be null. Create // the new (child) delegate with a reference to the parent for fallback purposes, // then ultimately reset this.delegate back to its original (parent) reference. // this behavior emulates a stack of delegates without actually necessitating one. // 在遞歸的時(shí)候疑故,跟蹤父級(jí)delegate杠览,新的遞歸調(diào)用引用上個(gè)方法的delegate BeanDefinitionParserDelegate parent = this.delegate; // 創(chuàng)建 BeanDefinitionParserDelegate 對(duì)象,并進(jìn)行設(shè)置到 delegate this.delegate = createDelegate(getReaderContext(), root, parent); // 檢查 <beans /> 根標(biāo)簽的命名空間是否為空纵势,或者是 http://www.springframework.org/schema/beans【1】 if (this.delegate.isDefaultNamespace(root)) { // 處理 profile 屬性踱阿。可參見(jiàn)《Spring3自定義環(huán)境配置 <beans profile="">》 【2】 String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); // We cannot use Profiles.of(...) since profile expressions are not supported // in XML config. See SPR-12458 for details. // 判定環(huán)境參數(shù)是否滿足钦铁,無(wú)效則不注冊(cè) if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if (logger.isDebugEnabled()) { logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + getReaderContext().getResource()); } return; } } } // 解析前處理目前是空處理软舌,可以繼承,由子類(lèi)去實(shí)現(xiàn) preProcessXml(root); // 解析xml為BeanDefinition并向容器注冊(cè)生成的BeanDefinition【3】 parseBeanDefinitions(root, this.delegate); // 解析后處理,目前為空?qǐng)?zhí)行牛曹,子類(lèi)可繼承處理 postProcessXml(root); // 設(shè)置為最初的BeanDefinitionParserDelegate this.delegate = parent; }
【1】 檢查
<beans />
根標(biāo)簽的命名空間是否為空葫隙,或者是http://www.springframework.org/schema/beans
【2】檢查beans標(biāo)簽的是否指定profile環(huán)境注冊(cè),若profile參數(shù)是不滿足條件躏仇,則不注冊(cè)
【3】解析element(<beans />
)下的<bean/>
元素并注冊(cè)到BeanDefinition的map容器中恋脚。
說(shuō)明:createDelegate
方法執(zhí)行主要是創(chuàng)建代理,然后代理首先初始化一些默認(rèn)的屬性焰手,DocumentDefaultsDefinition是存儲(chǔ)默認(rèn)配置的對(duì)象:default-lazy-init
糟描、default-merge
、default-autowire
书妻、default-dependency-check
船响、default-autowire-candidates
、default-init-method
躲履、default-destroy-method
见间。 -
parseBeanDefinitions處理邏輯解析
/** * Parse the elements at the root level in the document: "import", "alias", "bean". * * @param root the DOM root element of the document */ protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { // 如果該節(jié)點(diǎn)使用默認(rèn)命名空間,執(zhí)行默認(rèn)解析【1】 if (delegate.isDefaultNamespace(root)) { // root節(jié)點(diǎn)下的子節(jié)點(diǎn)【2】 NodeList nl = root.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; // 如果該節(jié)點(diǎn)使用默認(rèn)命名空間工猜,執(zhí)行默認(rèn)解析【3】 if (delegate.isDefaultNamespace(ele)) { parseDefaultElement(ele, delegate); } else { // 如果該節(jié)點(diǎn)非默認(rèn)命名空間米诉,執(zhí)行自定義解析【4】 delegate.parseCustomElement(ele); } } } } else {// 如果根節(jié)點(diǎn)非默認(rèn)命名空間,執(zhí)行自定義解析【5】 delegate.parseCustomElement(root); } }
【1】如果該節(jié)點(diǎn)使用默認(rèn)命名空間篷帅,執(zhí)行默認(rèn)解析
【2】root節(jié)點(diǎn)下的子節(jié)點(diǎn)
【3】如果該節(jié)點(diǎn)使用默認(rèn)命名空間史侣,執(zhí)行默認(rèn)解析
【4】如果該節(jié)點(diǎn)非默認(rèn)命名空間拴泌,執(zhí)行自定義解析
【5】如果該節(jié)點(diǎn)非默認(rèn)命名空間,執(zhí)行自定義解析 -
parseDefaultElement處理邏輯解析
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { // import標(biāo)簽 if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); // alias 解析 } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); //bean 解析 } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); // beans元素解析 } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { //遞歸解析beans doRegisterBeanDefinitions(ele); } }
-
processBeanDefinition處理邏輯解析
/** * Process the given bean element, parsing the bean definition and registering it with the registry. */ protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { // 委托BeanDefinition類(lèi)的parseBeanDefinitionElement方法進(jìn)行元素解析,返回Beandefinition 【1】 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { // 當(dāng)返回的bdHolder 不為空的情況下,若存在默認(rèn)標(biāo)簽的子節(jié)點(diǎn)下再有自定義屬性,還需要再次對(duì)自定義標(biāo)簽進(jìn)行解析.【2】 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. // 最終執(zhí)行注冊(cè)邏輯【3】 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. // 下發(fā)注冊(cè)事件惊橱,通知相關(guān)的監(jiān)聽(tīng)器蚪腐,這個(gè)bean已經(jīng)加載完成【4】 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
【1】委托BeanDefinition類(lèi)的parseBeanDefinitionElement方法進(jìn)行元素解析,返回Beandefinition ,此時(shí)的bdHolder實(shí)例已經(jīng)包含了我們配置文件中的各種屬性了,例如 : class,name,id,alias
【2】當(dāng)返回的bdHolder 不為空的情況下,若存在默認(rèn)標(biāo)簽的子節(jié)點(diǎn)下再有自定義屬性,還需要再次對(duì)自定義標(biāo)簽進(jìn)行解析.
【3】最終執(zhí)行BeanDefinition注冊(cè)邏輯
【4】下發(fā)注冊(cè)事件税朴,通知相關(guān)的監(jiān)聽(tīng)器回季,這個(gè)bean已經(jīng)加載完成
-
registryBeanDefinition的注冊(cè)邏輯分析
從代碼上分析我們的registryBeanDefinition的最終執(zhí)行是在是通過(guò)
public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
,注冊(cè)的過(guò)程是在解析xml過(guò)程中完成注冊(cè)邏輯的正林。//--------------------------------------------------------------------- // Implementation of BeanDefinitionRegistry interface //--------------------------------------------------------------------- // 注冊(cè)BeanDefinition @Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { // 校驗(yàn) beanName 與 beanDefinition 非空 Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { // 【1】 校驗(yàn)BeanDefinition泡一,這也是注冊(cè)前的最后一次校驗(yàn)了,主要是對(duì)屬性 methodOverrides 進(jìn)行校驗(yàn)卓囚。 ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } //【2】從緩存中獲取指定beanName的 BeanDefinition,主要 判斷bean name下是否已經(jīng)注冊(cè)過(guò)BeanDefinition BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); //【3】如果改BenDefinition已經(jīng)注冊(cè)诅病,如果不允許覆蓋的話哪亿,則拋出異常 if (existingDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } // 當(dāng)前要注冊(cè)的BeanDefinition的role 大于 已經(jīng)注冊(cè)過(guò)的BeanDefinition 打印info 日志 else if (existingDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (logger.isInfoEnabled()) { logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } // 當(dāng)前要注冊(cè)的BeanDefinition與已被覆蓋的BeanDefinition不是一個(gè)對(duì)象,打印Debug日志信息 else if (!beanDefinition.equals(existingDefinition)) { if (logger.isDebugEnabled()) { logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } // 打印 trace日志信息 else { if (logger.isTraceEnabled()) { logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } // 覆蓋已經(jīng)注冊(cè)的bean信息 this.beanDefinitionMap.put(beanName, beanDefinition); } // 【4】未注冊(cè)執(zhí)行注冊(cè)邏輯 else { // 判斷Bean的創(chuàng)建階段是否已經(jīng)開(kāi)啟贤笆,開(kāi)啟的話需要對(duì)beanDefinitionMap進(jìn)行線程保護(hù) if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) // beanDefinitionMap為全局變量蝇棉,加鎖保護(hù),防止創(chuàng)建階段和注冊(cè)階段的并發(fā)問(wèn)題 synchronized (this.beanDefinitionMap) { // 添加到BeanDefinition的map 容器中 this.beanDefinitionMap.put(beanName, beanDefinition); // 添加BeanName到 beanDefinitionNames中去(beanDefinitionNames初始化限制了大小為256芥永,所以變更的時(shí)候需要引入一個(gè)中間變量-主要是擴(kuò)容問(wèn)題) List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); // 更新最新的beanDefinitionNames updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; // 從 manualSingletonNames 移除 beanName removeManualSingletonName(beanName); } } else { // Still in startup registration phase // 添加到 BeanDefinition 到 beanDefinitionMap 中篡殷。 this.beanDefinitionMap.put(beanName, beanDefinition); // 添加 beanName 到 beanDefinitionNames 中 this.beanDefinitionNames.add(beanName); // 從 manualSingletonNames 移除 beanName removeManualSingletonName(beanName); } this.frozenBeanDefinitionNames = null; } // 【5】重新設(shè)置beanName對(duì)應(yīng)的緩存 if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }
【1】對(duì)
BeanDefinition
進(jìn)行校驗(yàn),這也是注冊(cè)過(guò)程中最后一次校驗(yàn)了埋涧,主要是針對(duì)AbstractBeanDefinition
的methodOverride
屬性進(jìn)行校驗(yàn)板辽。
【2】根據(jù)beanName從緩存中獲取BeanDefinition。
【3】如果緩存中已經(jīng)存在棘催,則根據(jù)allowBeanDefinitionOverriding標(biāo)簽判斷是否允許覆蓋劲弦,如果不允許覆蓋,則拋出BeanDefinitionStoreException
異常醇坝。
【4】若緩存中沒(méi)有beanName 的BeanDefinition
對(duì)象邑跪,則判斷當(dāng)前階段是否已經(jīng)開(kāi)始了Bean的創(chuàng)建階段,如果是則對(duì)僅限并發(fā)保護(hù)呼猪,對(duì)BeanDefinitionMap
進(jìn)行加鎖并發(fā)控制画畅。否則直接設(shè)置即可。
【5】若緩存存在改beanName或者單例bean集合中存在該beanName宋距,則調(diào)用#resetBeanDefinition(beanName)
方法轴踱,充值BeanDefinition緩存。整個(gè)階段的核心流程其實(shí)就是對(duì)beanDefinitionMap的操作谚赎,只要核心在于
this.beanDefinitionMap.put(beanName, beanDefinition)
方法寇僧,而B(niǎo)eanDefinition的存儲(chǔ)其實(shí)就是定義了個(gè)map摊腋,key為beanName,value為BeanDefinition嘁傀。
小結(jié)