美文网首页
ResourceLoader详解(三)--DefaultReso

ResourceLoader详解(三)--DefaultReso

作者: 北海北_6dc3 | 来源:发表于2019-03-19 18:07 被阅读0次

对象

ResourceLoader继承对象.png

DefaultResourceLoader目的

{@link ResourceLoader}接口的默认实现。由{@link ResourceEditor}使用,并作为{@link org.springframework.context.support.AbstractApplicationContext}的基类。也可以单独使用。

如果位置值是URL,则返回{@link UrlResource};如果是非URL路径或“classpath:”伪URL,则返回{@link ClassPathResource}。

构造函数

    //设置默认ClassLoder
    public DefaultResourceLoader() {
        this.classLoader = ClassUtils.getDefaultClassLoader();
    }

    public DefaultResourceLoader(@Nullable ClassLoader classLoader) {
        this.classLoader = classLoader;
    }
    //..setClassLoader、getClassLoader方法

我们可以看到构造函数的主要目的就是赋值classLoader

protocolResolvers

    //添加protocolResolvers
    public void addProtocolResolver(ProtocolResolver resolver) {
        Assert.notNull(resolver, "ProtocolResolver must not be null");
        this.protocolResolvers.add(resolver);
    }

    //获取
    public Collection<ProtocolResolver> getProtocolResolvers() {
        return this.protocolResolvers;
    }
    //调用核心方法
    @Override
    public Resource getResource(String location) {
        //我们看到,相当于一个拦截器,优先执行查找resource,找到即返回
        for (ProtocolResolver protocolResolver : this.protocolResolvers) {
            Resource resource = protocolResolver.resolve(location, this);
            if (resource != null) {
                return resource;
            }
        }
        //后续代码,不考虑拦截流程。
        if (location.startsWith("/")) {
            return getResourceByPath(location);
        }
        else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
            return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
        }
        else {
            try {
                // Try to parse the location as a URL...
                URL url = new URL(location);
                return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
            }
            catch (MalformedURLException ex) {
                // No URL -> resolve as resource path.
                return getResourceByPath(location);
            }
        }
    }

我们可以看到protocolResolvers,相当于对默认实现的一个增强,传入其他解析查找模式,如果匹配则返回。
默认查找方式主要分为三种
1.匹配开头斜杠和异常。getResourceByPath
2.匹配格式classpath:。ClassPathResource
3.尝试用FileUrlResource或者UrlResource获取
首先我们来分析第一种情况

getResourceByPath

    protected Resource getResourceByPath(String path) {
        return new ClassPathContextResource(path, getClassLoader());
    }
    /**
     * 通过实现ContextResource接口显式表达上下文相关路径的ClassPathResource,此方法重点在于实现ContextResource
     */
    protected static class ClassPathContextResource extends ClassPathResource implements ContextResource {
        //基于父类构造
        public ClassPathContextResource(String path, @Nullable ClassLoader classLoader) {
            super(path, classLoader);
        }

        @Override
        public String getPathWithinContext() {
            return getPath();
        }
        //基于当前路径的重新构建对象
        @Override
        public Resource createRelative(String relativePath) {
            String pathToUse = StringUtils.applyRelativePath(getPath(), relativePath);
            return new ClassPathContextResource(pathToUse, getClassLoader());
        }
    }

我们可以看到getResourceByPath,可以简单的看做对ClassPathResource 的增强。即调用ClassPathResource 进行解析。
ClassPathResource解析,查看第五节

从上可以看出,第一种情况和第二种情况都是调用ClassPathResource 实现

总结

DefaultResourceLoader功能有2:
1.增加基于protocolResolvers的拦截增强
2.基于ClassPathResource 、FileUrlResource、UrlResource解析,优先级从左到右

相关文章

网友评论

      本文标题:ResourceLoader详解(三)--DefaultReso

      本文链接:https://www.haomeiwen.com/subject/hnqbmqtx.html