技术杂谈

Spring IOC 源码解析三(BeanDefinitions

2018-11-17  本文已影响6人  香芋牛奶面包

引言

这期主要是解析BeanDefinitions的载入和注册的整个过程,整个过程看似非常复杂,其实我们可以分成几个部分去看: 1.载入 2.注册和解析
如果没有看过前面几期的话,建议先过一下前面几期

BeanDefinitions的载入

loadBeanDefinitions(String... locations)

public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
    Assert.notNull(locations, "Location array must not be null");
    int counter = 0;
    String[] var3 = locations;
    int var4 = locations.length;

    for(int var5 = 0; var5 < var4; ++var5) {
        String location = var3[var5];
        // 开始载入配置信息
        counter += this.loadBeanDefinitions(location);
    }

    return counter;
}

loadBeanDefinitions(String location, Set<Resource> actualResources)

public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
      // 获取 ResourceLoader
    ResourceLoader resourceLoader = this.getResourceLoader();
    if(resourceLoader == null) {
        throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
    } else {
        int loadCount;
        // 判断 resourceLoader 的类型是否属于ResourcePatternResolver类型
        if(!(resourceLoader instanceof ResourcePatternResolver)) {
            Resource resource = resourceLoader.getResource(location);
            // 调用子类的 loadBeanDefinitions(resource) 方法
            loadCount = this.loadBeanDefinitions((Resource)resource);
            if(actualResources != null) {
                actualResources.add(resource);
            }

            if(this.logger.isDebugEnabled()) {
                this.logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
            }

            return loadCount;
        } else {
            try {
                Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
                // 循环遍历载入
                loadCount = this.loadBeanDefinitions(resources);
                if(actualResources != null) {
                    Resource[] var6 = resources;
                    int var7 = resources.length;

                    for(int var8 = 0; var8 < var7; ++var8) {
                        Resource resource = var6[var8];
                        actualResources.add(resource);
                    }
                }

                if(this.logger.isDebugEnabled()) {
                    this.logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
                }

                return loadCount;
            } catch (IOException var10) {
                throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var10);
            }
        }
    }
}

loadBeanDefinitions(EncodedResource encodedResource)

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isInfoEnabled()) {
        logger.info("Loading XML bean definitions from " + encodedResource.getResource());
    }

    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    if (currentResources == null) {
        currentResources = new HashSet<EncodedResource>(4);
        this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }
    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException(
                "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try {
    // 获取到XML文件的inputStream流
        InputStream inputStream = encodedResource.getResource().getInputStream();
        try {
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            // 进行具体的xml文件流解析
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        }
        finally {
            inputStream.close();
        }
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(
                "IOException parsing XML document from " + encodedResource.getResource(), ex);
    }
    finally {
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove();
        }
    }
}

doLoadBeanDefinitions(InputSource inputSource, Resource resource)

class = org.springframework.beans.factory.xml.XmlBeanDefinitionReader

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
        throws BeanDefinitionStoreException {
    try {
        // 解析xml并返回Document对象,这里解析由DefaultDocumentLoader完成
        Document doc = doLoadDocument(inputSource, resource);
        // 解析 Document对象并注册
        return registerBeanDefinitions(doc, resource);
    }
    catch (BeanDefinitionStoreException ex) {
        throw ex;
    }
    catch (SAXParseException ex) {
        throw new XmlBeanDefinitionStoreException(resource.getDescription(),
                "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
    }
    catch (SAXException ex) {
        throw new XmlBeanDefinitionStoreException(resource.getDescription(),
                "XML document from " + resource + " is invalid", ex);
    }
    catch (ParserConfigurationException ex) {
        throw new BeanDefinitionStoreException(resource.getDescription(),
                "Parser configuration exception parsing XML from " + resource, ex);
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(resource.getDescription(),
                "IOException parsing XML document from " + resource, ex);
    }
    catch (Throwable ex) {
        throw new BeanDefinitionStoreException(resource.getDescription(),
                "Unexpected exception parsing XML document from " + resource, ex);
    }
}

BeanDefinitions的解析与注册

registerBeanDefinitions(doc, resource)

class = org.springframework.beans.factory.xml.XmlBeanDefinitionReader

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    // 创建 DefaultBeanDefinitionDocumentReader 解析xml资源文件
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    int countBefore = getRegistry().getBeanDefinitionCount();
    // 具体的解析开始
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

/**
 * 创建上下文对象
 */
public XmlReaderContext createReaderContext(Resource resource) {
    // 创建上下文对象 持有XmlBeanDefinitionReader 对象
    return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
            this.sourceExtractor, this, getNamespaceHandlerResolver());
}

/**
 * 创建XMl命名空间解析代理类,解析XML文件的依据。可以解析自定义XML文件
 */
public NamespaceHandlerResolver getNamespaceHandlerResolver() {
    if (this.namespaceHandlerResolver == null) {
        this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
    }
    return this.namespaceHandlerResolver;
}

/**
 * 创建默认的命名空间解析代理类
 */
protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
    return new DefaultNamespaceHandlerResolver(getResourceLoader().getClassLoader());
}

doRegisterBeanDefinitions(Element root)

class = org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    this.logger.debug("Loading bean definitions");
    Element root = doc.getDocumentElement();
    // 解析根节点
    this.doRegisterBeanDefinitions(root);
}

protected void doRegisterBeanDefinitions(Element root) {
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
    // 判断节点所属命名空间是否为spring默认(http://www.springframework.org/schema/beans)
    if(this.delegate.isDefaultNamespace(root)) {
        String profileSpec = root.getAttribute("profile");
        if(StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
            if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                if(this.logger.isInfoEnabled()) {
                    this.logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource());
                }

                return;
            }
        }
    }
     // 空实现
    this.preProcessXml(root);
    // 开始解析根节点
    this.parseBeanDefinitions(root, this.delegate);
    // 空实现
    this.postProcessXml(root);
    // 赋值生成的父对象。含有默认配置
    this.delegate = parent;
}

parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)

class = org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
      // 判断是否为默认命名空间
    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)) {
                        // 默认解析
                    this.parseDefaultElement(ele, delegate);
                } else {
                        // 执行自定义解析方法
                    delegate.parseCustomElement(ele);
                }
            }
        }
    } else {
            // 执行自定义解析方法
        delegate.parseCustomElement(root);
    }

}

默认解析

parseDefaultElement

class = org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        // 解析import标签
    if(delegate.nodeNameEquals(ele, "import")) {
        this.importBeanDefinitionResource(ele);
    } else if(delegate.nodeNameEquals(ele, "alias")) {
            // 解析alias标签
        this.processAliasRegistration(ele);
    } else if(delegate.nodeNameEquals(ele, "bean")) {
            // 解析bean标签
        this.processBeanDefinition(ele, delegate);
    } else if(delegate.nodeNameEquals(ele, "beans")) {
            // 解析beans标签
        this.doRegisterBeanDefinitions(ele);
    }

}

processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)

class = org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // 解析并包装成BeanDefinitionHolder
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if(bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

        try {
                // 向容器注册 BeanDefiniton,XmlReaderContext其实是持有容器的引用的
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
        } catch (BeanDefinitionStoreException var5) {
            this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
        }

        this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }

}

parseBeanDefinitionElement

自定义解析 parseCustomElement

class=org.springframework.beans.factory.xml.BeanDefinitionParserDelegate

public BeanDefinition parseCustomElement(Element ele) {
    return this.parseCustomElement(ele, (BeanDefinition)null);
}

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
    // 获取所属的命名空间地址
    String namespaceUri = this.getNamespaceURI(ele);
    // 上下文中获取DefaultNamespaceHandlerResolver 并根据命名空间地址获取对应的 Handler
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if(handler == null) {
        this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
        return null;
    } else {
            // 执行解析(this.readerContext 中持有BeanFactory注册对象,可以回调注册BeanDefinition信息)
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }
}

尾言

BeanDefinitions 到这里为止就被注册完成了,下期就是Spring重要的依赖注入了

博客原文地址戳这里

上一篇 下一篇

猜你喜欢

热点阅读