Spring源码之Resource加载源码解析(三)

ResourceLoader 架构概览

ResourceLoader接口用于返回Resource对象;其实现可以看作是一个生产Resource的工厂类。
《Spring源码之Resource加载源码解析(三)》
可以分为两类:
  第一类:默认资源加载器DefaultResourceLoader及其子类;
   Spring提供了一个适用于所有环境的DefaultResourceLoader实现,可以返回ClassPathResource、UrlResource;还提供一个用于web环境的ServletContextResourceLoader,它继承了DefaultResourceLoader的所有功能,又额外提供了获取ServletContextResource的支持。
 第二类: 应用上下文ApplicationContext接口及其实现类;
 ApplicationContext的主要实现类ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,前者默认从类路径加载配置文件,后者默认从文件系统中装载配置文件。本次不做说明,后面会单独介绍ApplicationContext。

ResourceLoader接口源码解析

//通过ResourceLoader获取资源
public interface ResourceLoader {

    //加载的类路径伪URL前缀:“classpath:”
    String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;

    //根据提供的location参数返回相应的Resource对象
    Resource getResource(String location);

    //返回加载这些Resource的ClassLoader
    ClassLoader getClassLoader();

}

ResourceLoader在进行加载资源时需要使用前缀来指定需要加载:“classpath:path”表示返回ClasspathResource,“http://path”和“file:path”表示返回UrlResource资源,如果不加前缀则需要根据当前上下文来决定,DefaultResourceLoader默认实现可以加载classpath资源

DefaultResourceLoader及其子类源码解析

public class DefaultResourceLoader implements ResourceLoader {
    //加载该资源类加载器
    private ClassLoader classLoader;


    //构造函数
    public DefaultResourceLoader() {
        //默认:实际资源访问时使用的线程上下文类加载器
        this.classLoader = ClassUtils.getDefaultClassLoader();
    }

    //构造函数
    public DefaultResourceLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    //设置类加载器
    public void setClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    //获取类加载器,未设置,则返回实际资源访问时使用的线程上下文类加载器
    public ClassLoader getClassLoader() {
        return (this.classLoader != null ? this.classLoader : ClassUtils.getDefaultClassLoader());
    }

    //根据提供的location参数返回相应的资源句柄Resource。
    public Resource getResource(String location) {
        Assert.notNull(location, "Location must not be null");
        //“classpath:”前缀,返回ClassPathResource对象
        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...
                //尝试将location转化为URL,再返回UrlResource对象
                URL url = new URL(location);
                return new UrlResource(url);
            }
            catch (MalformedURLException ex) {
                //不是URL,则解析为资源路径。
                return getResourceByPath(location);
            }
        }
    }


    //返回给定路径path上资源的资源句柄Resource。
    protected Resource getResourceByPath(String path) {
        //默认实现支持类路径位置
        return new ClassPathContextResource(path, getClassLoader());
    }


    //类加载路径下的资源
    private static class ClassPathContextResource extends ClassPathResource implements ContextResource {

        public ClassPathContextResource(String path, ClassLoader classLoader) {
            super(path, classLoader);
        }

        public String getPathWithinContext() {
            return getPath();
        }

        // 关键 -> 创建相相对于当前资源路径下的资源。
        // 假设当前的 file 路径为 D:/DEMO/HELLO.TXT,且 relativePath = GOOD.TXT
        // 则该方法创建的资源路径为 D:/DEMO/GOOD.TXT 
        @Override
        public Resource createRelative(String relativePath) {
            String pathToUse = StringUtils.applyRelativePath(getPath(), relativePath);
            return new ClassPathContextResource(pathToUse, getClassLoader());
        }
    }

}

//servlet上下文资源加载器
public class ServletContextResourceLoader extends DefaultResourceLoader {

    private final ServletContext servletContext;


    //构造函数
    public ServletContextResourceLoader(ServletContext servletContext) {
        this.servletContext = servletContext;
    }


    //此实现支持Web应用程序根目录下的文件路径。
    @Override
    protected Resource getResourceByPath(String path) {
        return new ServletContextResource(this.servletContext, path);
    }

}
//文件系统资源加载器
public class FileSystemResourceLoader extends DefaultResourceLoader {
    //将资源路径解析为文件系统路径。
    @Override
    protected Resource getResourceByPath(String path) {
        if (path != null && path.startsWith("/")) {
            path = path.substring(1);
        }
        return new FileSystemContextResource(path);
    }


    //文件系统里面的资源
    private static class FileSystemContextResource extends FileSystemResource implements ContextResource {

        public FileSystemContextResource(String path) {
            super(path);
        }

        public String getPathWithinContext() {
            return getPath();
        }
    }

}

//类相关资源加载器
public class ClassRelativeResourceLoader extends DefaultResourceLoader {

    private final Class clazz;

    //创建一个指定类的相关资源加载器
    public ClassRelativeResourceLoader(Class clazz) {
        Assert.notNull(clazz, "Class must not be null");
        this.clazz = clazz;
        setClassLoader(clazz.getClassLoader());
    }

    protected Resource getResourceByPath(String path) {
        return new ClassRelativeContextResource(path, this.clazz);
    }

    //获取类路径下的资源文件
    private static class ClassRelativeContextResource extends ClassPathResource implements ContextResource {

        private final Class clazz;

        public ClassRelativeContextResource(String path, Class clazz) {
            super(path, clazz);
            this.clazz = clazz;
        }

        public String getPathWithinContext() {
            return getPath();
        }

        @Override
        public Resource createRelative(String relativePath) {
            String pathToUse = StringUtils.applyRelativePath(getPath(), relativePath);
            return new ClassRelativeContextResource(pathToUse, this.clazz);
        }
    }

}
    原文作者:Spring Cloud
    原文地址: https://blog.csdn.net/lh513828570/article/details/75094451
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞