zoukankan      html  css  js  c++  java
  • spring IOC篇二:xml的核心逻辑处理(doLoadBeanDefinitions(inputSource, encodedResource.getResource()))

    2.1 doLoadBeanDefinitions(inputSource, encodedResource.getResource())

    /**
         * Actually load bean definitions from the specified XML file.
         * @param inputSource the SAX InputSource to read from
         * @param resource the resource descriptor for the XML file
         * @return the number of bean definitions found
         * @throws BeanDefinitionStoreException in case of loading or parsing errors
         * @see #doLoadDocument
         * @see #registerBeanDefinitions
         */
        protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
                throws BeanDefinitionStoreException {
            try {
                 //获取XML的验证方式,加载XML文件得到对应的Document
                Document doc = doLoadDocument(inputSource, resource);
                //根据返回的Dcoument注册Bean信息
                return registerBeanDefinitions(doc, resource);
            } 
           .........................................
       } 

    2,2 Document doc = doLoadDocument(inputSource, resource);

     /**
         * Actually load the specified document using the configured DocumentLoader.
         * @param inputSource the SAX InputSource to read from
         * @param resource the resource descriptor for the XML file
         * @return the DOM Document
         * @throws Exception when thrown from the DocumentLoader
         * @see #setDocumentLoader
         * @see DocumentLoader#loadDocument
         */
        protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
            return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
                    getValidationModeForResource(resource), isNamespaceAware());
        }

    2.2.3  getValidationModeForResource(resource) DTD或者XSD文件格式的读取

    /**
         * Gets the validation mode for the specified {@link Resource}. If no explicit
         * validation mode has been configured then the validation mode is
         * {@link #detectValidationMode detected}.
         * <p>Override this method if you would like full control over the validation
         * mode, even when something other than {@link #VALIDATION_AUTO} was set.
         */
        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).
            return VALIDATION_XSD;
        }

    自动检测的代码逻辑分析:

    先定义一个变量 isDtdValidated 是否是DTD约束 默认是 false,然后一行行的读取xml资源文件,如果里面包含 DOCTYPE  字符串则是DTD约束,则上返回,停止自动检测。

    int detectedMode = detectValidationMode(resource);
    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;
                    }
                    if (hasOpeningTag(content)) {
                        // End of meaningful data...
                        break;
                    }
                }
                return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
            }

    2,2,4 getEntityResolver() 获取资源文件约束的声明

    entityResolver接口有以下一个方法

    public abstract InputSource resolveEntity (String publicId,
                                                   String systemId)
            throws SAXException, IOException;
    
    }

    他接受两个参数:publicIdsystemId,并返回InputSource 对象

    如果是XSD资源文件:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"  
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
        xmlns:cutesource="http://blog.csdn.net/cutesource/schema/people"  
        xsi:schemaLocation="  
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
    http://blog.csdn.net/cutesource/schema/people http://blog.csdn.net/cutesource/schema/people.xsd">  
        <cutesource:people id="cutesource" name="袁志俊" age="27"/>  
    </beans> 
    将会读取到以下两个参数:
    publicId:null
    systemId:http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    如果是 DTD约束:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper>
    ...............................
    </mapper>
    将会读取到以下两个参数:
    publicId:-//mybatis.org//DTD
    systemId:http://mybatis.org/dtd/mybatis-3-mapper.dtd
    通过getEntityResolver方法获取EntityResolver接口对象,DelegatingEntityResolver为EntityResolver的实现类。
    
    protected EntityResolver getEntityResolver() {
            if (this.entityResolver == null) {
                // Determine default EntityResolver to use.
                ResourceLoader resourceLoader = getResourceLoader();
                if (resourceLoader != null) {
        如果资源加载器不为空,则使用ResourceEntityResolver对象进行文件约束的声明
                    this.entityResolver = new ResourceEntityResolver(resourceLoader);
                }
                else {
                    this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());
                }
            }
            return this.entityResolver;
        }

    2.2.5 new ResourceEntityResolver(resourceLoader)

    public DelegatingEntityResolver(ClassLoader classLoader) {
            // 判断是否是DTD约束
               this.dtdResolver = new BeansDtdResolver();
           //  如果是XSD约束 在获取声明的默认路经是:
          // META-INF/spring.schemas
            this.schemaResolver = new PluggableSchemaResolver(classLoader);
        }

    2.3 解析并注册 BeanDefinitions

     将文件装换为Document以后,接下来的提取以及注册Bean就是我们的重头戏。

    /**
         * Register the bean definitions contained in the given DOM document.
         * Called by {@code loadBeanDefinitions}.
         * <p>Creates a new instance of the parser class and invokes
         * {@code registerBeanDefinitions} on it.
         * @param doc the DOM document
         * @param resource the resource descriptor (for context information)
         * @return the number of bean definitions found
         * @throws BeanDefinitionStoreException in case of parsing errors
         * @see #loadBeanDefinitions
         * @see #setDocumentReaderClass
         * @see BeanDefinitionDocumentReader#registerBeanDefinitions
         */
        public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
      // 使用DefaultBeanDefinitionDocumentReader 实例化BeanDefinitionDocumentReader 对象
            BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    // 记录统计前BeanDefinition的加载个数
            int countBefore = getRegistry().getBeanDefinitionCount();
    // 加载以及注册Bean

     //  这里使用到了单一职责原则,将逻辑处理委托给单一的类进行处理,这个逻辑处理类就是 BeanDefinitionDocumentReader 对象

            documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    // 统计本次加载Beanfinition的个数
            return getRegistry().getBeanDefinitionCount() - countBefore;
        }

    继续深入registerBeanDefinitions方法:

    /**
         * This implementation parses bean definitions according to the "spring-beans" XSD
         * (or DTD, historically).
         * <p>Opens a DOM Document; then initializes the default settings
         * specified at the {@code <beans/>} level; then parses the contained bean definitions.
         */
        @Override
        public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
            this.readerContext = readerContext;
            logger.debug("Loading bean definitions");
            Element root = doc.getDocumentElement();
            doRegisterBeanDefinitions(root);
        }

    继续深入doRegisterBeanDefinitions方法:doRegisterBeanDefinitions算开始真正解析XML文件了。

    protected void doRegisterBeanDefinitions(Element root) {
            // Any nested <beans> elements will cause recursion in this method. In
            // order to propagate and preserve <beans> default-* attributes correctly,
            // keep track of the current (parent) delegate, which may be null. Create
            // the new (child) delegate with a reference to the parent for fallback purposes,
            // then ultimately reset this.delegate back to its original (parent) reference.
            // this behavior emulates a stack of delegates without actually necessitating one.
            BeanDefinitionParserDelegate parent = this.delegate;
            this.delegate = createDelegate(getReaderContext(), root, parent);
           // 处理profile 属性
            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)) {
                        return;
                    }
                }
            }
             // 空代码留给子类去实现 模板设计模式 继承 DefaultBeanDefinitionDocumentReader 的子类咋XML解析前做一些处理,可以实现此方法
            preProcessXml(root);
            // 解析除了 profile以外的属性
            parseBeanDefinitions(root, this.delegate);
            // 空代码留给子类去实现 模板设计模式 继承 DefaultBeanDefinitionDocumentReader 的子类咋XML解析后做一些处理,可以实现此方法
            
            postProcessXml(root);
    
            this.delegate = parent;
        }

    2.4 判断标签的解析方式

    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
          // 对Bean的处理
            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);
            }
        }
  • 相关阅读:
    Key-Value Memory Network
    Deep Mask Memory Network with Semantic Dependency and Context Moment for Aspect Level Sentiment Clas
    Deep Memory Network在Aspect Based Sentiment方向上的应用
    Deep Memory Network 深度记忆网络
    Self Attention 自注意力机制
    Attention基本公式及其变种
    *端策略优化算法(PPO)
    Policy Gradient 算法
    一本通 农场派对
    A
  • 原文地址:https://www.cnblogs.com/histlyb/p/8976635.html
Copyright © 2011-2022 走看看