spring源码解析bean定义三(<import>、alias解析)

前言

上次介绍了bean定义解析部分的xml验证和<beans>标签默认属性解析,接着上次解析节奏开始。

正文

上一次介绍到这个方法

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions的这行代码

//     bean定义解析
      parseBeanDefinitions(root, this.delegate);

进入这个方法

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

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

进入到这个方法

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseDefaultElement

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

下次继续。

最后

本次介绍到这里,以上内容仅供参考。

扫码关注

进群讨论

快到碗里来

!

猜你喜欢

转载自my.oschina.net/u/3775437/blog/1810425