06.Spring 资源加载 - ResourceLoader
基本概念
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 将会确定具体的资源访问策略,从而将应用程序和具体的资源访问策略分离开来,这就体现了策略模式的优势。
参考
06.Spring 资源加载 - ResourceLoader的更多相关文章
- Spring资源加载器抽象和缺省实现 -- ResourceLoader + DefaultResourceLoader(摘)
概述 对于每一个底层资源,比如文件系统中的一个文件,classpath上的一个文件,或者一个以URL形式表示的网络资源,Spring 统一使用 Resource 接口进行了建模抽象,相应地,对于这些资 ...
- spring资源加载结构解析
1.spring中资源加载使用resources的原因? 在java将不同资源抽象成url,然后通过注册不同的hander来处理不同读取逻辑,一般hander使用协议的前缀来命名,如http,jar, ...
- spring 资源加载使用说明
Spring 提供了一个强大加载资源的机制,不但能够通过“classpath:”.“file:” 等资源地址前缀识别不同的资源类型,还支持Ant 风格带通配符的资源地址. 首先,我们来了解一下Spri ...
- 05.Spring 资源加载 - Resource
基本概念 Spring 把所有能记录信息的载体,如各种类型的文件.二进制流等都称为资源. 对 Spring 开发者来说,最常用的资源就是 Spring 配置文件(通常是一份 XML 格式的文件). S ...
- Spring资源加载基础ClassLoader
1 ClassLoader工作机制 1.1 ClassLoader作用 寻找类字节码文件并构造出类在JVM内部表示的组件.负责运行时查找和装入Class字节码文件 1.2 装载步骤 1.2.1 装载 ...
- Spring 资源加载
pom.xml ``` org.springframework spring-core 4.3.14.RELEASE org.springframework spring-beans 4.3.16.R ...
- 【死磕 Spring】----- IOC 之 Spring 统一资源加载策略
原文出自:http://cmsblogs.com 在学 Java SE 的时候我们学习了一个标准类 java.net.URL,该类在 Java SE 中的定位为统一资源定位器(Uniform Reso ...
- spring资源访问接口和资源加载接口
spring 资源访问接口 JDK提供的资源访问类,如java.net.URL.File等,不能很好地满足各种资源的访问需求,比如缺少从类路径或者Web容器的上下文中获取资源的操作类. 鉴于此,spr ...
- 简说Spring中的资源加载
声明: 本文若有 任何纰漏.错误,请不吝指正!谢谢! 问题描述 遇到一个关于资源加载的问题,因此简单的记录一下,对Spring资源加载也做一个记录. 问题起因是使用了@PropertySource来进 ...
随机推荐
- 洛谷【P1303】A*B Problem
题目传送门:https://www.luogu.org/problemnew/show/P1303 高精度乘法板子题,灵性地回忆一下小学时期列竖式的草稿纸即可. 时间复杂度:\(O(len^2)\) ...
- bzoj 3158 千钧一发 —— 最小割
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3158 \( a[i] \) 是奇数则满足条件1,是偶数则显然满足条件2: 因为如果把两个奇数 ...
- 洛谷 P4525 & P4526 [模板] 自适应辛普森积分
题目:https://www.luogu.org/problemnew/show/P4525 https://www.luogu.org/problemnew/show/P4526 学习辛普森积分:h ...
- Hyperledger fablic 0.6 在centos7环境下的安装与部署
原文:http://blog.csdn.net/zhaoliang1131/article/details/54617274 Hyperledger Fabric超级账本 项目约定共同遵守的 基本原则 ...
- netty中的ByteBuf
网络数据的基本单位总是字节.Java NIO 提供了 ByteBuffer 作为它 的字节容器,但是这个类使用起来过于复杂,而且也有些繁琐. Netty 的 ByteBuffer 替代品是 ByteB ...
- linux使用JMETER进行分布式压力测试
1. 下载jmeter tgz文件 http://jmeter.apache.org/download_jmeter.cgi 2. 登录linux服务器,创建jmeter目录,rz上传jmeter ...
- 问题:JsonConvert;结果:JSON详解
JSON详解 JSON的全称是”JavaScript Object Notation”,意思是JavaScript对象表示法,它是一种基于文本,独立于语言的轻量级数据交换格式.XML也是一种数据交换格 ...
- J2EE 工作中注意事项
[转载于http://www.cnblogs.com/hemingwang0902/archive/2012/01/06/2314215.html] 根据当前项目中代码存在的一些问题,编写了一个编码注 ...
- SVN使用技巧和参考文档总结
以下文章为网上收集: myEclipse 8.5下SVN环境的搭建(重点推荐) SVN建立版本库,配置用户和权限 Tortoise SVN使用方法,简易图解 版本控制软件SVN使用方法详解 学习笔记 ...
- 【254】◀▶IEW-Unit19
Unit 19 Technology Communication I.名词性从句在雅思写作中的运用 英语中哪些位置可以放名词? 1)主语 2)宾语 3)表语 4)同位语 名词的位置放一个句子=名词性从 ...