前言node
本文轉自「天河聊技術」微信公衆號spring
上次介紹了bean定義解析部分的xml驗證和<beans>標籤默認屬性解析,接着上次解析節奏開始。緩存
正文微信
上一次介紹到這個方法app
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions的這行代碼less
// bean定義解析 parseBeanDefinitions(root, this.delegate);
進入這個方法ide
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitionsui
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { // 根節點是不是命名空間 http://www.springframework.org/schema/beans if (delegate.isDefaultNamespace(root)) { 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; if (delegate.isDefaultNamespace(ele)) { parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
進入到這個方法this
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseDefaultElementspa
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { // import 標籤解析 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); } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // 內部beans標籤 doRegisterBeanDefinitions(ele); } }
// import 標籤解析 if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); }
進入這個方法
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#importBeanDefinitionResource
protected void importBeanDefinitionResource(Element ele) { // resource 解析屬性 String location = ele.getAttribute(RESOURCE_ATTRIBUTE); if (!StringUtils.hasText(location)) { getReaderContext().error("Resource location must not be empty", ele); return; } // Resolve system properties: e.g. "${user.dir}" 佔位符系統屬性解析 location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location); Set<Resource> actualResources = new LinkedHashSet<>(4); // Discover whether the location is an absolute or relative URI 判斷路徑是相對仍是絕對 boolean absoluteLocation = false; try { absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute(); } catch (URISyntaxException ex) { // cannot convert to an URI, considering the location relative // unless it is the well-known Spring prefix "classpath*:" } // Absolute or relative? if (absoluteLocation) { // 若是是絕地路徑 try { int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources); if (logger.isDebugEnabled()) { logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]"); } } catch (BeanDefinitionStoreException ex) { getReaderContext().error( "Failed to import bean definitions from URL location [" + location + "]", ele, ex); } } else { // No URL -> considering resource location as relative to the current file. try { int importCount; Resource relativeResource = getReaderContext().getResource().createRelative(location); if (relativeResource.exists()) { // 調用bean定義加載 importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource); actualResources.add(relativeResource); } else { String baseLocation = getReaderContext().getResource().getURL().toString(); // 調用bean定義加載 importCount = getReaderContext().getReader().loadBeanDefinitions( StringUtils.applyRelativePath(baseLocation, location), actualResources); } if (logger.isDebugEnabled()) { logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]"); } } catch (IOException ex) { getReaderContext().error("Failed to resolve current resource location", ele, ex); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]", ele, ex); } } Resource[] actResArray = actualResources.toArray(new Resource[0]); // 觸發import bean定義解析完畢 getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele)); }
返回到這個方法
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseDefaultElement的這行代碼
// alias else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); }
進入到這個方法
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processAliasRegistration
protected void processAliasRegistration(Element ele) { // 獲取name屬性值 String name = ele.getAttribute(NAME_ATTRIBUTE); // 獲取alias屬性值 String alias = ele.getAttribute(ALIAS_ATTRIBUTE); boolean valid = true; if (!StringUtils.hasText(name)) { getReaderContext().error("Name must not be empty", ele); valid = false; } if (!StringUtils.hasText(alias)) { getReaderContext().error("Alias must not be empty", ele); valid = false; } if (valid) { try { // 從xml讀取上下文中獲取bean定義註冊器註冊別名 getReaderContext().getRegistry().registerAlias(name, alias); } catch (Exception ex) { getReaderContext().error("Failed to register alias '" + alias + "' for bean with name '" + name + "'", ele, ex); } // 觸發別名已註冊事件 getReaderContext().fireAliasRegistered(name, alias, extractSource(ele)); } }
找到這行代碼
// 從xml讀取上下文中獲取bean定義註冊器註冊別名 getReaderContext().getRegistry().registerAlias(name, alias);
進入這個方法
org.springframework.context.support.GenericApplicationContext#registerAlias
@Override public void registerAlias(String beanName, String alias) { // 註冊別名 this.beanFactory.registerAlias(beanName, alias); }
進入到這個方法
org.springframework.core.SimpleAliasRegistry#registerAlias
@Override 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) { // 若是別名和名字一致,從緩存map中刪除別名 if (alias.equals(name)) { this.aliasMap.remove(alias); } else { String registeredName = this.aliasMap.get(alias); if (registeredName != null) { // name值和alias值不能同樣 if (registeredName.equals(name)) { // An existing alias - no need to re-register return; } // alias名不能覆蓋name名值 if (!allowAliasOverriding()) { throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" + name + "': It is already registered for name '" + registeredName + "'."); } } // 檢查註冊的別名是否已存在 checkForAliasCircle(name, alias); this.aliasMap.put(alias, name); } } }
返回到這個方法
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processAliasRegistration這行代碼
// 觸發別名已註冊事件 getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
返回到這個方法
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseDefaultElement這行代碼<bean>標籤解析
// bean else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); }
下次繼續。
最後
本次介紹到這裏,以上內容僅供參考。