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

来源:互联网 发布:哈登什么水平知乎 编辑:程序博客网 时间:2024/05/20 09:21

ResourceLoader 架构概览

ResourceLoader接口用于返回Resource对象;其实现可以看作是一个生产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);        }    }}
原创粉丝点击