基本概念

ResourceLoader 接口,在 Spring 中用于加载资源,通过它可以获取一个 Resouce 对象。


内部构造

首先来看它的接口定义:

public interface ResourceLoader {// 从 classpath 加载资源时的前缀 String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX; // 关键-> 取得 Resource 对象,即获取资源 Resource getResource(String location); ClassLoader getClassLoader(); }

再来看它的继承关系,如下所示:

  • DefaultResourceLoader : 作为 ResourceLoader 接口的直接实现类,该类实现了基本的资源加载功能,可以实现对单个资源的加载。

  • ResourcePatternResolver :该接口继承了 ResourceLoader,定义了加载多个资源的方法, 可以实现对多个资源的加载。


DefaultResourceLoader

上面介绍过该类通过实现 ResourceLoader 接口实现了加载单个资源的功能。它的子类通过继承它来实现具体的资源访问策略。下面来探究下该类如何加载单个资源:

public Resource getResource(String location) {Assert.notNull(location, "Location must not be null");// ① 是否以"/" 开头if (location.startsWith("/")) { return getResourceByPath(location); } // ② 是否以"classpath:" 开头,若是则表示该资源类型为 ClassPathResource else if (location.startsWith(CLASSPATH_URL_PREFIX)) { return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader()); } else { try { // ③若都不是,则当成 UrlResource 来处理 URL url = new URL(location); return new UrlResource(url); }catch (MalformedURLException ex) { // 若不是 UrlResource,则仍当作 ① 情况来处理 return getResourceByPath(location); } } }

观察代码,发现在拿到资源的路径 loaction 后,会根据 location 的形式分成三种情况来处理:

  • 以 “/” 开头:默认调用类中的 getResourceByPath 方法处理。它的子类通过重写该方法实现不同形式的资源的访问。

  • 以 “classpath:” 开头:当成 ClassPathResource 资源对待。

  • 其他情况: 当成 UrlResource 资源对待,如果访问资源抛出异常,则调用 getResourceByPath 来完成资源的访问。


ResourcePatternResolver

该接口继承自 ResourceLoader 接口,在其基础上增加了同时对多个资源的访问。首先来看它的接口定义:

public interface ResourcePatternResolver extends ResourceLoader { String CLASSPATH_ALL_URL_PREFIX = "classpath*:"; // 例如使用 ant 风格的路径,匹配路径下的多个资源 Resource[] getResources(String locationPattern) throws IOException; }

1.PathMatchingResourcePatternResolver

该类是 ResourcePatternResolver 接口的直接实现类,它是基于模式匹配的,默认使用AntPathMatcher 进行路径匹配,它除了支持 ResourceLoader 支持的前缀外,还额外支持 “classpath*” ,下面来探究下该类是如何实现对多个资源的访问。

public Resource[] getResources(String locationPattern) throws IOException {Assert.notNull(locationPattern, "Location pattern must not be null");// 是否以 "classpath*:" 开头 if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) { // 通过 getPathMatcher 方法取得 PathMatcher ,默认只有 AntPathMatcher 一个实现类 // 通过 isPattern 方法判断 "classpath*:" 之后的路径是否包含 "*" 或 "?" if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) { // 关键 -> 找到所有匹配路径(ant 风格)的资源 return findPathMatchingResources(locationPattern); }else { // 关键 -> 通过类加载器查找 return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length())); } }else { int prefixEnd = locationPattern.indexOf(":") + 1; // 判断资源路径 ":" 之后的部分是否包含 "*" 或 "?" if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) { return findPathMatchingResources(locationPattern); }else { // 若不存在表示是单个资源,则通过从构造函数传入的 ResourceLoader 取得 return new Resource[] {getResourceLoader().getResource(locationPattern)}; } } }

观察代码:

  • 该方法首先会去判断资源路径是否是类路径下的资源(以 “classpath*:” 开头),然后再去判断路径是否允许存在多个匹配的资源(路径中包含 “*” 或 “?”)。

  • 只要资源路径允许多个匹配的资源,就会通过 findPathMatchingResources 方法寻找所有的匹配资源;

  • 若资源路径只存在单个匹配,则通过类加载器寻找类路径下的资源(findAllClassPathResources) ,其他资源则通过 ResourceLoader 的 getResource 方法获取。


2.ApplicationContext

通过上面的继承关系图可知,该接口继承了 ResourcePatternResolver 接口,说明它也集成了对对单个或多个资源的访问功能。

当 Spring 需要进行资源访问时,实际上并不需要直接使用 Resource 实现类,而是调用 getResource 方法来获取资源。

当通过 ApplicationContext 实例获取 Resource 实例时,它将会负责选择具体的 Resource 的实现类。代码如下:

//通过 ApplicationContext访问资源Resource res = ctx.getResource("some/resource/path/myTemplate.txt);

从上面代码中无法确定 Spring 将哪个实现类来访问指定资源,Spring 将采用和 ApplicationContext 相同的策略来访问资源。也就是说:如果 ApplicationContext 是 FileSystemXmlApplicationContext,res 就是 FileSystemResource 实例;如果 ApplicationContext 是 ClassPathXmlApplicationContext,res 就是 ClassPathResource 实例;如果 ApplicationContext 是 XmlWebApplicationContext,res 是 ServletContextResource 实例。

也就是说 ApplicationContext 将会确定具体的资源访问策略,从而将应用程序和具体的资源访问策略分离开来,这就体现了策略模式的优势。


参考

  • https://www.ibm.com/developerworks/cn/java/j-lo-spring-resource/

转载于:https://www.cnblogs.com/moxiaotao/p/9349532.html

06.Spring 资源加载 - ResourceLoader相关推荐

  1. Spring资源加载器抽象和缺省实现 -- ResourceLoader + DefaultResourceLoader(摘)

    概述 对于每一个底层资源,比如文件系统中的一个文件,classpath上的一个文件,或者一个以URL形式表示的网络资源,Spring 统一使用 Resource 接口进行了建模抽象,相应地,对于这些资 ...

  2. Spring Boot : 资源加载器

    1.美图 2.概述 前言参考: 源码:Spring boot 主程序的功能(启动流程) ResourceLoader接口,在 Spring 中用于加载资源,通过它可以获取一个Resouce 对象.使用 ...

  3. 【Bug档案01】Spring Boot的控制器+thymeleaf模板 -使用中出现静态资源加载路径不当的问题 -解决时间:3h

    [Bug档案01]Spring Boot的控制器+thymeleaf模板 -使用中出现静态资源加载路径不当的问题 -解决时间:3h 参考文章: (1)[Bug档案01]Spring Boot的控制器+ ...

  4. Spring Boot||html页面的css等资源加载失败

    背景 这几天在用spring boot 框架来实现一个网站,静态页面已经写好,创建完成spring项目后将html文件.css等资源文件分别扔到了/项目名称/src/main/resources/te ...

  5. Spring MVC中静态资源加载

    问题:MVC 静态资源加载,包括 js.css.image加载不出来 由于web.xml中dispatcherServlet中 url-pattern 使用 / 拦截所有访问,而导致静态资源也交给了D ...

  6. 【sping揭秘】6、IOC容器之统一资源加载策略

    Spring中的resource 我们先看看类之间的关系 注意我们的application是间接继承了resourceloader的,也就是说我们的application其实就是一个resourcel ...

  7. spring bean加载过程_Spring源码剖析3:Spring IOC容器的加载过程

    本文转自五月的仓颉 https://www.cnblogs.com/xrq730 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https ...

  8. Spring BeanDefinition加载

    Spring容器里通过BeanDefinition对象来表示Bean,BeanDefinition描述了Bean的配置信息.而BeanDefinitionRegistry接口提供了向容器注册,删除,获 ...

  9. composition java_阿里P7架构师通过源码浅析Java中的资源加载

    一. 前提 最近在做一个基础组件项目刚好需要用到JDK中的资源加载,这里说到的资源包括类文件和其他静态资源,刚好需要重新补充一下类加载器和资源加载的相关知识,整理成一篇文章. 二. 什么是类加载器 虚 ...

最新文章

  1. R语言编写自定义函数基于ggsumarystats函数计算每个分组的统计值、自定义可视化分组分面条形图,并在X轴标签下方添加分组对应的统计值(样本数N、中位数median、四分位数的间距iqr)
  2. ML之NBLoR:利用NB(朴素贝叶斯)、LoR(逻辑斯蒂回归)算法(+TfidfVectorizer)对Rotten Tomatoes影评数据集进行文本情感分析—五分类预测
  3. WeChat授权Token验证体系:用token来隐藏微信用户的openid不用用户名与密码了, 与cookie与session很相似
  4. RedHat7.0 设置weblogic开机自启动
  5. Python list 和 tuple 使用小记
  6. C++ 基于 Visual C++6.0 的 DLL 编程实现
  7. object转date类型_js-最常用的类型判断
  8. 使用Lucene检索文档中的关键字
  9. 【Oracle】创建概要文件
  10. Shell脚本学习指南(一)——入门
  11. 两款Java中小医院信息管理系统源码
  12. USB打印服务器作用,沁恒股份USB打印机服务器方案概述
  13. becon帧 wifi_无线路由器Beacon时槽值设置为100同500有什么区别?是不是设置越高WIFI信号的传输距离就越远越强?...
  14. 胡耀文教你:裂变8级、转化率32%、K值7.4的老带新式分销全复盘
  15. MFC下载—时间记录
  16. C++数据结构第13课、类族结构的进化
  17. 《卷积网络》深度卷积网络实例
  18. Antd 表格 ellipsis属性兼容性问题
  19. 微型计算机中的pcl是指,PCL中的类
  20. python下载安装过程——超详细!

热门文章

  1. 1475 m进制转十进制
  2. NHibernate中,查询SqlServer数据库多个实体对象
  3. 求解N个值中最大的k个数,N远大于k
  4. acwing算法题--分组背包问题
  5. python统计文本中单词出现次数
  6. 如何将网页保存为图片_如何一键保存网页上的所有图片至 iPhone 相册
  7. linux coredump配置与调试
  8. centos7-yum安装与卸载
  9. 基于epoll实现一个IO多路复用的回声服务器
  10. 执行phpize Cannot find config.m4