Spring IOC源码解读

spring源码日记07: import标签解析

2020-02-11  本文已影响0人  BugPool

所有文章已迁移至csdn,csdn个人主页https://blog.csdn.net/chaitoudaren
本节介绍一下import标签的解析,import标签用于引进新的资源文件,例如一个spring.xml需要引入redis,jdbc等配置文件。主要是要像读者介绍一下递归加载的思想,包括beans标签也使用到了递归的思想,不过beans是递归加载bean,而import是递归加载资源文件。

<beans>
  <import resource="redis.xml">
  <import resource="${jdbc.url}">
<beans>
// DefaultBeanDefinitionDocumentReader.java
    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);
        }
        // 解析beans标签,解析该标签实际是递归调用doRegisterBeanDefinitions,前面提到的parent delegate
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            // recurse
            doRegisterBeanDefinitions(ele);
        }
    }

解析import标签

// DefaultBeanDefinitionDocumentReader.java
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}"
        // 转化系统变量 e.g. "${jdbc.url}" 需要转化为对应地址
        location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

        // 每一个被实际加载的资源都会被加入这个set中
        // 在资源被成功加载后,通知import-processed事件哪些资源文件又被加载了
        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 {
                // 绝对路径,直接使用递归调用
                // 这里的loadBeanDefinitions肯定多少有点印象
                // 该函数是loadBeanDefinitions(EncodedResource encodedResource)的重载,将会递归的加载资源
                int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
                if (logger.isTraceEnabled()) {
                    logger.trace("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;
                // 相对路径,则需要先验证路径下是否有文件,之后直接调用递归的loadBeanDefinitions加载文件
                Resource relativeResource = getReaderContext().getResource().createRelative(location);
                if (relativeResource.exists()) {
                    importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
                    actualResources.add(relativeResource);
                }
                else {
                    String baseLocation = getReaderContext().getResource().getURL().toString();
                    importCount = getReaderContext().getReader().loadBeanDefinitions(
                            StringUtils.applyRelativePath(baseLocation, location), actualResources);
                }
                if (logger.isTraceEnabled()) {
                    logger.trace("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]);
        getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
    }
上一篇下一篇

猜你喜欢

热点阅读