spring源碼解析bean定義三(、alias解析)

前言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);
      }

下次繼續。

 

最後

本次介紹到這裏,以上內容僅供參考。

相關文章
相關標籤/搜索