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来进 ...
随机推荐
- docker-ce安装与搭建私有仓库
https://www.cnblogs.com/sszhou/p/7389144.html 系统环境centos7 ###docker-ce安装###1.卸载老版本,较老版本的Docker被称为doc ...
- Azure上部署FTP服务
FTP是个比较复杂的协议,其协议分为控制层和数据层,工作模式分为主动和被动两种模式. 在默认的Active模式下其工作原理如下: 可以看到,客户端发起FTP的请求道服务器端,FTP的端口是21.用户在 ...
- HDOJ(1069)最长下降子序列
每个箱子可有3种叠加方式,所以有3*n个箱子.将箱子按长度由大到小排序,有求箱子按宽度的最长下降子序列的高度之和即可. #include<cstdio> #include<algor ...
- 【转】 Pro Android学习笔记(四一):Fragment(6):数据保留
目录(?)[-] 通过fragment参数实现数据保留 对TitleFragment进行修改 对DetailActivity进行修改 通过savedInstanceState进行数据保留 保留frag ...
- Oracle数据库安全性设计
一.什么是安全的系统 安全性建设是一个长期并且卓绝的工作.作为一个符合标准的企业级系统,我们认为税务系统应该具备以下的安全性特点: ◆高可用性 ◆对敏感数据的访问控制能力. ◆监测用户行为的审计能力. ...
- 【jQuery】slice()方法的使用
[jQuery]slice()方法的使用 slice()方法:从已有的数组中返回选定的元素. 语法: arrayObj.slice(start, end) ...
- java中的接口和抽象类的区别
1.接口从用户的角度(使用实现的代码)看问题. 2.接口由编译器强制的一个模块间协作的合约. 3.无成员变量. 4.成员函数只能声明不能实现,(jdk1.8中的default 方法可以有方法体). 接 ...
- numpy.matlib.randn(标准正态分布)
#网址 http://docs.scipy.org/doc/numpy/reference/generated/numpy.matlib.randn.html#numpy.matlib.randn n ...
- Ok6410裸机驱动学习(二)ARM基础知识
1.ARM工作模式 ARM微处理器支持7种工作模式,分别为: l 用户模式(usr):ARM处理器正常的程序执行状态(Linux用户态程序) l 快速中断模式(fiq):用于高速数据传输或通道处理 ...
- Struts2 配置项
基础Constants struts.devMode 可选值true,false (默认false),在开发模式下,struts2的动态重新加载配置和资源文件的功能会默认生效.同时开发模式下也会提供 ...