zoukankan      html  css  js  c++  java
  • spring源码解析-解析xml到IOC容器-spring加载文件对象

    1、Resource: 接口 对资源的抽象,其实现类代表资源的访问策略

       继承InputStreamSource接口,提供获取输入流核心接口

    InputStream getInputStream() throws IOException;
    AbstractResource          抽象类
        FileSystemResource    文件路径资源类
        ByteArrayResource     二进制流资源类
        ClassPathResource     classpath路径资源类
        UrlResource           url资源类    

    1.1、ClasspathResource:加载类路径下文件

    // 1. 实例化对象
    public ClassPathResource(String path, @Nullable ClassLoader classLoader) {
      Assert.notNull(path, "Path must not be null");
      String pathToUse = StringUtils.cleanPath(path);
      if (pathToUse.startsWith("/")) {
        pathToUse = pathToUse.substring(1);
      }
      this.path = pathToUse;
      this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
    }
    // 获取输入流对象
    @Override
    public InputStream getInputStream() throws IOException {
      InputStream is;
      if (this.clazz != null) {
        is = this.clazz.getResourceAsStream(this.path);
      }
      else if (this.classLoader != null) {
        is = this.classLoader.getResourceAsStream(this.path);
      }
      else {
        is = ClassLoader.getSystemResourceAsStream(this.path);
      }
      if (is == null) {
        throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
      }
      return is;
    }

    2、XmlValidationModeDetector:XML验证模式检测器(DTD、XSD)

    // XML文档类型判断
    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;
          }
          // DTD判断
          if (hasDoctype(content)) {
            isDtdValidated = true;
            break;
          }
          // XSD判断
          if (hasOpeningTag(content)) {
            break;
          }
        }
        return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
      } catch (CharConversionException ex) {
        return VALIDATION_AUTO;
      } finally {
        reader.close();
      }
    }            

    3、DocumentLoader:文档加载器

    // 核心接口,加载指定文档
    Document loadDocument(InputSource inputSource, EntityResolver entityResolver, 
      ErrorHandler errorHandler,
    int validationMode, boolean namespaceAware) throws Exception;

    3.1、DefaultDocumentLoader:默认的文档加载器

    // 实现加载文档
    @Override
    public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
      ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
      // 创建文件构建器工厂
      DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
      // 创建文档构建器
      DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
      // 解析文档
      return builder.parse(inputSource);
    }
    • 创建文件构造器工厂
    // validationMode:校验模式(3:XSD)(2:DTD)
    // namespaceAware:返回的工厂是否要提供对XML名称空间的支持
    protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware)
                throws ParserConfigurationException {
    
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      factory.setNamespaceAware(namespaceAware);
    
      if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
        factory.setValidating(true);
        if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
          factory.setNamespaceAware(true);
          try {
            factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
          } catch (IllegalArgumentException ex) {
            ParserConfigurationException pcex = new ParserConfigurationException(
                                "Unable to validate using XSD: Your JAXP provider [" + factory +
                                "] does not support XML Schema. Are you running on Java 1.4 with Apache Crimson? " +
                                "Upgrade to Apache Xerces (or Java 1.5) for full XSD support.");
            pcex.initCause(ex);
            throw pcex;
          }
        }
      }
      return factory;
    }
    • 创建文档构建器
    // factory:文档构建器工厂(DocumentBuilderFactoryImpl)
    // entityResolver:对象解析器(ResourceEntityResolver)
    // errorHandler:解析错误处理器(SimpleSaxErrorHandler)
    protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory,
                @Nullable EntityResolver entityResolver, @Nullable ErrorHandler errorHandler)
                throws ParserConfigurationException {
      DocumentBuilder docBuilder = factory.newDocumentBuilder();
      if (entityResolver != null) {
        docBuilder.setEntityResolver(entityResolver);
      }
      if (errorHandler != null) {
        docBuilder.setErrorHandler(errorHandler);
      }
      return docBuilder;
    }
    •  解析文档
    // is:XML文档输入流
    public Document parse(InputSource is) throws SAXException, IOException {
      if (is == null) {
        throw new IllegalArgumentException(
          DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
          "jaxp-null-input-source", null));
        }
      if (fSchemaValidator != null) {
        if (fSchemaValidationManager != null) {
          fSchemaValidationManager.reset();
          fUnparsedEntityHandler.reset();
        }
        resetSchemaValidator();
      }
      domParser.parse(is);
      Document doc = domParser.getDocument();
      domParser.dropDocumentReferences();
      return doc;
    }

     3.2、解析xml文件为Document  DOMParser(domParser.parse(is))

    // 解析输入流
    public void parse(InputSource inputSource) throws SAXException, IOException {
      try {
        XMLInputSource xmlInputSource = new XMLInputSource(inputSource.getPublicId(), inputSource.getSystemId(), null);
        xmlInputSource.setByteStream(inputSource.getByteStream());
        xmlInputSource.setCharacterStream(inputSource.getCharacterStream());
        xmlInputSource.setEncoding(inputSource.getEncoding());
        // 调用父类XMLParser的parse方法            
        parse(xmlInputSource);
      } catch (XMLParseException e) {
        Exception ex = e.getException();
        if (ex == null) {
          LocatorImpl locatorImpl = new LocatorImpl();
          locatorImpl.setPublicId(e.getPublicId());
          locatorImpl.setSystemId(e.getExpandedSystemId());
          locatorImpl.setLineNumber(e.getLineNumber());
          locatorImpl.setColumnNumber(e.getColumnNumber());
          throw new SAXParseException(e.getMessage(), locatorImpl);
        }
        if (ex instanceof SAXException) {
          throw (SAXException)ex;
        }
        if (ex instanceof IOException) {
          throw (IOException)ex;
        }
        throw new SAXException(ex);
      } catch (XNIException e) {
        Exception ex = e.getException();
        if (ex == null) {
          throw new SAXException(e.getMessage());
        }
        if (ex instanceof SAXException) {
          throw (SAXException)ex;
        }
        if (ex instanceof IOException) {
          throw (IOException)ex;
        }
        throw new SAXException(ex);
      }
    }
    • XMLParser (parse(XMLImputSource))
    // 解析输入流
    public void parse(XMLInputSource inputSource) throws XNIException, IOException {
      if (securityManager == null) {
        securityManager = new XMLSecurityManager(true);
        fConfiguration.setProperty(Constants.SECURITY_MANAGER, securityManager);
      }
      if (securityPropertyManager == null) {
        securityPropertyManager = new XMLSecurityPropertyManager();
        fConfiguration.setProperty(Constants.XML_SECURITY_PROPERTY_MANAGER, securityPropertyManager);
      }
      reset();
      // 调用XML11Configuration的parse(XMLInputSource)方法
      fConfiguration.parse(inputSource);
    }
    • XML11Configuration (parse(XMLInputSource))
    // 解析输入流
    public void parse(XMLInputSource source) throws XNIException, IOException {
      if (fParseInProgress) {
        throw new XNIException("FWK005 parse may not be called while parsing.");
      }
      fParseInProgress = true;
      try {
        setInputSource(source);
        // 调用本类的parse(boolean)方法
        parse(true);
      } catch (XNIException ex) {
        if (PRINT_EXCEPTION_STACK_TRACE)
          ex.printStackTrace();
        throw ex;
      } catch (IOException ex) {
        if (PRINT_EXCEPTION_STACK_TRACE)
          ex.printStackTrace();
        throw ex;
      } catch (RuntimeException ex) {
        if (PRINT_EXCEPTION_STACK_TRACE)
          ex.printStackTrace();
        throw ex;
      } catch (Exception ex) {
        if (PRINT_EXCEPTION_STACK_TRACE)
          ex.printStackTrace();
        throw new XNIException(ex);
      } finally {
        fParseInProgress = false;
        this.cleanup();
      }
    }
    // 解析
    public boolean parse(boolean complete) throws XNIException, IOException {
      if (fInputSource != null) {
        try {
          fValidationManager.reset();
          fVersionDetector.reset(this);
          fConfigUpdated = true;
          resetCommon();
          short version = fVersionDetector.determineDocVersion(fInputSource);
          if (version == Constants.XML_VERSION_1_1) {
            initXML11Components();
            configureXML11Pipeline();
            resetXML11();
          } else {
            configurePipeline();
            reset();
          }
          fConfigUpdated = false;
          fVersionDetector.startDocumentParsing((XMLEntityHandler) fCurrentScanner, version);
          fInputSource = null;
        } catch (XNIException ex) {
          if (PRINT_EXCEPTION_STACK_TRACE)
            ex.printStackTrace();
          throw ex;
        } catch (IOException ex) {
          if (PRINT_EXCEPTION_STACK_TRACE)
            ex.printStackTrace();
          throw ex;
        } catch (RuntimeException ex) {
          if (PRINT_EXCEPTION_STACK_TRACE)
            ex.printStackTrace();
          throw ex;
        } catch (Exception ex) {
          if (PRINT_EXCEPTION_STACK_TRACE)
            ex.printStackTrace();
          throw new XNIException(ex);
        }
      }
    
      try {
        // 调用XMLDocumentFragementScannerImpl的scanDocument(boolean)方法
        return fCurrentScanner.scanDocument(complete);
      } catch (XNIException ex) {
        if (PRINT_EXCEPTION_STACK_TRACE)
          ex.printStackTrace();
        throw ex;
      } catch (IOException ex) {
        if (PRINT_EXCEPTION_STACK_TRACE)
          ex.printStackTrace();
        throw ex;
      } catch (RuntimeException ex) {
        if (PRINT_EXCEPTION_STACK_TRACE)
          ex.printStackTrace();
        throw ex;
      } catch (Exception ex) {
        if (PRINT_EXCEPTION_STACK_TRACE)
          ex.printStackTrace();
        throw new XNIException(ex);
      }
    }
    • XMLDocumentFragementScannerImpl (scanDocument(boolean)) XML文档片段扫描仪
    // 循环解析结果处理
    public boolean scanDocument(boolean complete) throws IOException, XNIException {
      fEntityManager.setEntityHandler(this);
      // 调用子类XMLNSDocumentScannerImpl的next()方法,执行具体解析
      int event = next();
      do {
        switch (event) {
          case XMLStreamConstants.START_DOCUMENT :
            break;
          case XMLStreamConstants.START_ELEMENT :
            break;
          case XMLStreamConstants.CHARACTERS :
            fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
            fDocumentHandler.characters(getCharacterData(),null);
            break;
          case XMLStreamConstants.SPACE:
            break;
          case XMLStreamConstants.ENTITY_REFERENCE :
            fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
                break;
          case XMLStreamConstants.PROCESSING_INSTRUCTION :
            fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
            fDocumentHandler.processingInstruction(getPITarget(),getPIData(),null);
            break;
          case XMLStreamConstants.COMMENT :
            fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
            fDocumentHandler.comment(getCharacterData(),null);
            break;
          case XMLStreamConstants.DTD :
            break;
          case XMLStreamConstants.CDATA:
            fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
            fDocumentHandler.startCDATA(null);
            fDocumentHandler.characters(getCharacterData(),null);
            fDocumentHandler.endCDATA(null);
            break;
          case XMLStreamConstants.NOTATION_DECLARATION :
            break;
          case XMLStreamConstants.ENTITY_DECLARATION :
            break;
          case XMLStreamConstants.NAMESPACE :
            break;
          case XMLStreamConstants.ATTRIBUTE :
            break;
          case XMLStreamConstants.END_ELEMENT :
            break;
          default :
            throw new InternalError("processing event: " + event);
        }
        // 调用子类XMLNSDocumentScannerImpl的next()方法,执行具体解析
        event = next();
      } while (event!=XMLStreamConstants.END_DOCUMENT && complete);
      if(event == XMLStreamConstants.END_DOCUMENT) {
        fDocumentHandler.endDocument(null);
        return false;
      }
      return true;
    }
    • XMLNSDocumentScannerImpl (next())  XMLNS文档扫描仪
    // 执行解析
    public int next() throws IOException, XNIException {
      if((fScannerLastState == XMLEvent.END_ELEMENT) && fBindNamespaces){
        fScannerLastState = -1;
        fNamespaceContext.popContext();
      }
      // 调用父类XMLDocumentScannerImpl的next()方法
      return fScannerLastState = super.next();
    }
    • XMLDocumentScannerImpl (next())   XML文档扫描仪
    public int next() throws IOException, XNIException {
      // 调用XMLDocumentScannerImpl.XMLDeclDriver的next()方法
      return fDriver.next();
    }
    • XMLDocumentScannerImpl.XMLDeclDriver (next())  XML Decl驱动程序
    // 解析细节
    public int next() throws IOException, XNIException {
      setScannerState(SCANNER_STATE_PROLOG);
      setDriver(fPrologDriver);
      try {
        if (fEntityScanner.skipString(xmlDecl)) {
          fMarkupDepth++;
          if (XMLChar.isName(fEntityScanner.peekChar())) {
            fStringBuffer.clear();
            fStringBuffer.append("xml");
            while (XMLChar.isName(fEntityScanner.peekChar())) {
              fStringBuffer.append((char)fEntityScanner.scanChar(null));
            }
            String target = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length);
            fContentBuffer.clear() ;
            scanPIData(target, fContentBuffer);
            fEntityManager.fCurrentEntity.mayReadChunks = true;
            return XMLEvent.PROCESSING_INSTRUCTION ;
          } else {
            scanXMLDeclOrTextDecl(false);
            fEntityManager.fCurrentEntity.mayReadChunks = true;
            return XMLEvent.START_DOCUMENT;
          }
        } else {
          fEntityManager.fCurrentEntity.mayReadChunks = true;
          return XMLEvent.START_DOCUMENT;
        }
      } catch (EOFException e) {
        reportFatalError("PrematureEOF", null);
        return -1;
      }
    }

    注:以上扫描器依赖关系

    XMLDocumentFragmentScannerImpl:XML文档片段扫描器
        XMLDocumentScannerImpl:(子类)XML文档扫描仪
                XMLDeclDriver:(内部类)XML Decl驱动程序
            XMLNSDocumentScannerImpl:(子类) XMLNS文档扫描仪
  • 相关阅读:
    RabbitMQ学习笔记
    Eclipse下JRebel的安装和基本使用
    通过HTTP响应头让浏览器自动刷新
    CentOS6.5安装Jenkins
    Windows快捷操作技巧
    关于代码压缩混淆加密整理;
    一款优雅的小程序拖拽排序组件实现
    记一次 Mac CA证书 问题
    微信小程序-Swiper和下拉刷新组件
    WeUI Picker组件 源代码分析
  • 原文地址:https://www.cnblogs.com/pascall/p/13158841.html
Copyright © 2011-2022 走看看