spring源码解析bean定义加载二(DTD、XSD验证和加载)

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

前言

本文转自“天河聊技术”微信公众号

接着上一篇文章的bean定义解析继续

 

正文

上一次解析到这个方法org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.support.EncodedResource)这行代码

//           加载bean定义
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
//        加载xml文档
         Document doc = doLoadDocument(inputSource, resource);
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
   return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
         getValidationModeForResource(resource), isNamespaceAware());
}

isNamespaceAware() 返回XML解析器是否应该具有XML名称空间

进入这个方法org.springframework.beans.factory.xml.XmlBeanDefinitionReader#getValidationModeForResource

protected int getValidationModeForResource(Resource resource) {
      int validationModeToUse = getValidationMode();
      if (validationModeToUse != VALIDATION_AUTO) {
         return validationModeToUse;
      }
      int detectedMode = detectValidationMode(resource);
      if (detectedMode != VALIDATION_AUTO) {
         return detectedMode;
      }
      // Hmm, we didn't get a clear indication... Let's assume XSD,
      // since apparently no DTD declaration has been found up until
      // detection stopped (before finding the document's root tag).
//    如果没有解析到xml验证模式就采用XSD验证
      return VALIDATION_XSD;
   }

进入这一行的这个方法

int detectedMode = detectValidationMode(resource);
protected int detectValidationMode(Resource resource) {
   if (resource.isOpen()) {
      throw new BeanDefinitionStoreException(
            "Passed-in Resource [" + resource + "] contains an open stream: " +
            "cannot determine validation mode automatically. Either pass in a Resource " +
            "that is able to create fresh streams, or explicitly specify the validationMode " +
            "on your XmlBeanDefinitionReader instance.");
   }

   InputStream inputStream;
   try {
      inputStream = resource.getInputStream();
   }
   catch (IOException ex) {
      throw new BeanDefinitionStoreException(
            "Unable to determine validation mode for [" + resource + "]: cannot open InputStream. " +
            "Did you attempt to load directly from a SAX InputSource without specifying the " +
            "validationMode on your XmlBeanDefinitionReader instance?", ex);
   }

   try {
      return this.validationModeDetector.detectValidationMode(inputStream);
   }
   catch (IOException ex) {
      throw new BeanDefinitionStoreException("Unable to determine validation mode for [" +
            resource + "]: an error occurred whilst reading from the InputStream.", ex);
   }
}

进入这一行的这个方法

return this.validationModeDetector.detectValidationMode(inputStream);

org.springframework.util.xml.XmlValidationModeDetector#detectValidationMode

public int detectValidationMode(InputStream inputStream) throws IOException {
      // Peek into the file to look for DOCTYPE.
      BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
      try {
         boolean isDtdValidated = false;
         String content;
         while ((content = reader.readLine()) != null) {
//          跳过 注释
            content = consumeCommentTokens(content);
            if (this.inComment || !StringUtils.hasText(content)) {
               continue;
            }
//          是否有DOCTYPE声明
            if (hasDoctype(content)) {
               isDtdValidated = true;
               break;
            }
//          判断文件是否是以xml标记开头
            if (hasOpeningTag(content)) {
               // End of meaningful data...
               break;
            }
         }
//       如果找到了DOCTYPE声明就启用DTD验证,如果没有就启用XSD验证
         return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
}
   catch (CharConversionException ex) {
      // Choked on some character encoding...
      // Leave the decision up to the caller. 异常spring就会去猜测一种解析类型去解析
      return VALIDATION_AUTO;
   }
   finally {
      reader.close();
   }
}

返回到这个方法

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadDocument

protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
   return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
         getValidationModeForResource(resource), isNamespaceAware());
}

loadDocument()加载xmnl文档,底层是java的api

返回到这个方法

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions

//        注册bean定义
         return registerBeanDefinitions(doc, resource);
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//    创建bean定义阅读器
      BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
      int countBefore = getRegistry().getBeanDefinitionCount();
//    注册bean定义之前先创建XmlReaderContext
      documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
      return getRegistry().getBeanDefinitionCount() - countBefore;
   }

进入这行代码

//     注册bean定义之前先创建
      documentReader.registerBeanDefinitions(doc, createReaderContext(resource));

进入这个方法

public XmlReaderContext createReaderContext(Resource resource) {
   return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
         this.sourceExtractor, this, getNamespaceHandlerResolver());
}
public NamespaceHandlerResolver getNamespaceHandlerResolver() {
   if (this.namespaceHandlerResolver == null) {
      this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
   }
   return this.namespaceHandlerResolver;
}
protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
   ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader());
   return new DefaultNamespaceHandlerResolver(cl);
}
public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) {
   this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION);
}
public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";

可以看到是从这个路径下加载的spring.handlers

返回到这个方法

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions这一行代码

//     注册bean定义之前先创建
      documentReader.registerBeanDefinitions(doc, createReaderContext(resource));

进入这个方法

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

@Override
   public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
      this.readerContext = readerContext;
      logger.debug("Loading bean definitions");
//    获取xml文档根节点
      Element root = doc.getDocumentElement();
//    从xml文件中解析bean定义
      doRegisterBeanDefinitions(root);
   }

进入这个方法

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

protected void doRegisterBeanDefinitions(Element root) {
//     加载bean定义
      BeanDefinitionParserDelegate parent = this.delegate;
      this.delegate = createDelegate(getReaderContext(), root, parent);

//    如果根节点是命名空间 http://www.springframework.org/schema/beans
      if (this.delegate.isDefaultNamespace(root)) {
         String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
         if (StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                  profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
//          解析环境配置文件
            if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
               if (logger.isInfoEnabled()) {
                  logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                        "] not matching: " + getReaderContext().getResource());
               }
               return;
            }
         }
      }

进入这个方法

protected BeanDefinitionParserDelegate createDelegate(
         XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) {
//    bean定义解析委托
      BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
//    bean定义默认配置
      delegate.initDefaults(root, parentDelegate);
      return delegate;
   }

进入这个方法

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#initDefaults(org.w3c.dom.Element, org.springframework.beans.factory.xml.BeanDefinitionParserDelegate)

public void initDefaults(Element root, @Nullable BeanDefinitionParserDelegate parent) {
//    解析默认的bean定义解析配置
      populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root);
//    触发默认的bean定义事件
      this.readerContext.fireDefaultsRegistered(this.defaults);
   }

进入这个方法

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#populateDefaults

//  解析beans标签
   protected void populateDefaults(DocumentDefaultsDefinition defaults, @Nullable DocumentDefaultsDefinition parentDefaults, Element root) {
//    解析default标签值 是否是default-lazy-init,默认值是false,父配置文件的属性会覆盖子配置文件的属性
      String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
      if (DEFAULT_VALUE.equals(lazyInit)) {
         // Potentially inherited from outer  sections, otherwise falling back to false.
         lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE);
      }
      defaults.setLazyInit(lazyInit);

//    default-merge 是否是这个值,默认值是false
      String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE);
      if (DEFAULT_VALUE.equals(merge)) {
         // Potentially inherited from outer  sections, otherwise falling back to false.
         merge = (parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE);
      }
      defaults.setMerge(merge);

//    default-autowire 是否是这个值,默认值是no
      String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
      if (DEFAULT_VALUE.equals(autowire)) {
         // Potentially inherited from outer  sections, otherwise falling back to 'no'.
         autowire = (parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE);
      }
      defaults.setAutowire(autowire);

//    default-autowire-candidate 是否最为候选bean被自动注入
      if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) {
         defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE));
      }
      else if (parentDefaults != null) {
         defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates());
      }

//    default-init-method
      if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
         defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
      }
      else if (parentDefaults != null) {
         defaults.setInitMethod(parentDefaults.getInitMethod());
      }

//    default-destroy-method
      if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
         defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
      }
      else if (parentDefaults != null) {
         defaults.setDestroyMethod(parentDefaults.getDestroyMethod());
      }

      defaults.setSource(this.readerContext.extractSource(root));
   }

返回到这个方法

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions这一行

//           解析环境配置文件
            if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {

下片文章继续。

 

最后

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

转载于:https://my.oschina.net/u/3775437/blog/1810424

你可能感兴趣的:(spring源码解析bean定义加载二(DTD、XSD验证和加载))