Resource理解

1、什么是Resource

当咱们学习Spring时,咱们总会在xml中对bean进行声明,而后再经过下面的代码片断来获取bean。代码以下:java

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Context {

  public static void main(String[] args) {
    
    ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring.xml");//一、加载配置文件
    System.err.println(ctx.getBean("stu").toString());//二、经过配置文件获取一个bean并打印

   }
}

上面第一行代码加载了一个资源文件Spring.xml,这个资源文件在Spring中属于Resource的一种。这样讲,Spring把各类类型的文件,二进制流都称之为Resource,只不过对于Spring开发者来讲,Resource大多都是xml文件。web

Resource是一个接口,接口里边定义了很是多关于文件的操做策略,好比spring

  • exists():判断资源是否存在
  • getURL():获取资源的URL
  • getFilename():获取资源的名称
  • ......(方法很是多,我就不一一列举了)

Resource 接口是具体资源访问策略的抽象,也是全部资源访问类所实现的接口。Resource 接口自己没有提供访问任何底层资源的实现逻辑,针对不一样的底层资源,Spring 将会提供不一样的 Resource 实现类,不一样的实现类负责不一样的资源访问逻辑。数据库

很是重要的一点,这也是Spring Resource设计最美妙的地方,那就是Spring 在Resource资源处理上采用啦策略模式,这也是我为何上面把Resource接口中的方法称之为策略的缘由了!api

若是还不了解Java 策略模式的朋友请先自行学习!数组

2、Spring Resource接口类结构图

为了更好地理解,在这里我先放一张策略模式的UML图,它的具体内容本文不讲。函数

 

 

 

 

好了!图片放上去了,那么策略模式Resource体系上如何体现出来呢?学习

  • 一、Resource接口至关于咱们的策略
  • 二、下面全部的实现类,包括AbstractResource在内都属于咱们的具体策略实现
  • 三、你可能要问,那么咱们的context角色到哪里去了呢?哈哈,作生意不能忘了咱们的老本啊!它就是咱们的IOC容器ApplicationContext,它是咱们策略模式中最最最具备决策能力的老大了

至于为何容器就能够处理咱们的Resource,我接下去会说到!spa

很明显,Resource是资源的最高抽象,一般咱们的应用程序不是都从classpath下去加载咱们的xml文件,咱们也能够经过一个URL,URI,InputStream等方式获取一个资源,这就是Spring把资源的获取方式和资源的定义之间解耦了!.net

3、ResourceLoader接口

  • ResourceLoader:该接口实现类的实例能够得到一个 Resource 实例。。

ResourceLoader 接口里有以下方法:

  • Resource getResource(String location):该接口仅包含这个方法,该方法用于返回一个 Resource 实例。

ApplicationContext 的实现类都实现 ResourceLoader 接口,而该接口又返回一个Resource实例,所以 ApplicationContext 可用于直接获取 Resource 实例,这也是为何容器就能够处理Resource的缘由!

4、spring 直接提供了多种开箱即用的 Resource 实现

1.UrlResource


UrlResource 封装了一个 java.net.URL 对象,用来访问 URL 能够正常访问的任意对象,好比文件、an HTTP target, an FTP target, 等等。全部的 URL 均可以用一个标准化的字符串来表示。如经过正确的标准化前缀,能够用来表示当前 URL 的类型,当中就包括用于访问文件系统路径的 file:,经过 http 协议访问资源的 http:,经过 ftp 协议访问资源的 ftp:,还有不少……

能够显式化地使用 UrlResource 构造函数来建立一个 UrlResource,不过一般咱们能够在调用一个 api 方法是,使用一个表明路径的 String 参数来隐式建立一个 UrlResource。对于后一种状况,会由一个 javabean PropertyEditor 来决定建立哪种 Resource。若是路径里包含某一个通用的前缀(如 classpath:),PropertyEditor 会根据这个通用的前缀来建立恰当的 Resource;反之,若是 PropertyEditor 没法识别这个前缀,会把这个路径做为一个标准的 URL 来建立一个 UrlResource。

2.ClassPathResource


可使用 ClassPathResource 来获取类路径上的资源。ClassPathResource 可使用线程上下文的加载器、调用者提供的加载器或指定的类中的任意一个来加载资源。

ClassPathResource 能够从类路径上加载资源,其可使用线程上下文加载器、指定加载器或指定的 class 类型中的任意一个来加载资源。

当类路径上资源存于文件系统中,ClassPathResource 支持以 java.io.File 的形式访问,可当类路径上的资源存于还没有解压(没有 被Servlet 引擎或其余可解压的环境解压)的 jar 包中,ClassPathResource 就再也不支持以 java.io.File 的形式访问。鉴于上面所说这个问题,spring 中各式 Resource 实现都支持以 jave.net.URL 的形式访问。

能够显式使用 ClassPathResource 构造函数来建立一个 ClassPathResource ,不过一般咱们能够在调用一个 api 方法时,使用一个表明路径的 String 参数来隐式建立一个 ClassPathResource。对于后一种状况,会由一个 javabean PropertyEditor 来识别路径中 classpath: 前缀,从而建立一个 ClassPathResource。

3.FileSystemResource

这是针对 java.io.File 提供的 Resource 实现。显然,咱们可使用 FileSystemResource 的 getFile() 函数获取 File 对象,使用 getURL() 获取 URL 对象。

4.ServletContextResource

这是为了获取 web 根路径的 ServletContext 资源而提供的 Resource 实现。

ServletContextResource 彻底支持以流和 URL 的方式访问,可只有当 web 项目是已解压的(不是以 war 等压缩包形式存在)且该 ServletContext 资源存于文件系统里,ServletContextResource 才支持以 java.io.File 的方式访问。至于说到,咱们的 web 项目是否已解压和相关的 ServletContext 资源是否会存于文件系统里,这个取决于咱们所使用的 Servlet 容器。若 Servlet 容器没有解压 web 项目,咱们能够直接以 JAR 的形式的访问,或者其余能够想到的方式(如访问数据库)等。

5.InputStreamResource

这是针对 InputStream 提供的 Resource 实现。建议,在确实没有找到其余合适的 Resource 实现时,才使用 InputSteamResource。若是能够,尽可能选择 ByteArrayResource 或其余基于文件的 Resource 实现来代替。

与其余 Resource 实现已比较,InputStreamRsource 倒像一个已打开资源的描述符,所以,调用 isOpen() 方法会返回 true。除了在须要获取资源的描述符或须要从输入流屡次读取时,都不要使用 InputStreamResource 来读取资源。

6.ByteArrayResource

这是针对字节数组提供的 Resource 实现。能够经过一个字节数组来建立 ByteArrayResource。

当须要从字节数组加载内容时,ByteArrayResource 是一个不错的选择,使用 ByteArrayResource 能够不用求助于 InputStreamResource。

5、策略模式在Spring中使用有什么优点

Spring 应用须要进行资源访问时,实际上并不须要直接使用 Resource 实现类,而是调用 ApplicationContext 实例的 getResource() 方法来得到资源,ApplicationContext 将会负责选择 Resource 的实现类,也就是肯定具体的资源访问策略,从而将应用程序和具体的资源访问策略分离开来。

既然有那么多的优点,下面就在来解释咱们上面的第一段代码,为何要使用ClassPathXmlApplicationContext这个类来对资源进行加载?

咱们都知道,在容器ApplicationContext下有不少的实现,好比FileSystemXmlApplicationContext,ClassPathXmlApplicationContext,XmlWebApplicationContext,并且咱们加载配置文件的方式一般也是使用它们来进行加载,在Spring中,ApplicationContext的实现类顾名思义也是对应了咱们Resource接口的一些实现策略,好比ClassPathResource,FileSystemResource等。

相关文章
相关标签/搜索