热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Spring中策略模式的应用:Resource接口详解

本文探讨了在Spring框架中如何利用Resource接口实现资源访问策略。Resource接口作为资源访问策略的抽象,通过多种实现类支持不同类型的资源访问。

一. 理论背景


在 Spring 框架中,读取配置文件是一个常见的需求。为了满足这一需求,Spring 提供了一个名为 Resource 的接口。Resource 接口定义了访问资源的基本方法,是一个抽象的资源访问策略。

Resource 接口的主要方法包括:

  • getInputStream(): 定位并打开资源,返回资源的输入流。每次调用都会返回一个新的输入流,调用者需确保关闭输入流。
  • exists(): 判断资源是否存在。
  • isOpen(): 检查资源是否已经打开。如果资源不能多次读取,每次读取后应显式关闭,以防止资源泄漏。
  • getDescription(): 返回资源的描述信息,通常用于资源处理出错时提供详细信息,如全限定文件名或实际 URL。
  • getFile(): 返回资源对应的 File 对象。
  • getURL(): 返回资源对应的 URL 对象。

Resource 接口本身不包含具体的资源访问实现逻辑,而是由不同的实现类来提供。Spring 为 Resource 接口提供了多种实现类,每种实现类负责不同的资源访问逻辑。

Resource 接口与策略模式

Resource 接口是策略模式的一个典型应用。Resource 接口定义了资源访问策略,但具体的实现策略由不同的实现类提供。客户端程序只需与 Resource 接口耦合,无需关心底层的具体实现,从而实现了资源访问策略的灵活切换。

Spring 为 Resource 接口提供的实现类包括:

  • UrlResource: 访问网络资源。
  • ClassPathResource: 访问类加载路径中的资源。
  • FileSystemResource: 访问文件系统中的资源。
  • ServletContextResource: 访问相对于 ServletContext 路径的资源。
  • InputStreamResource: 访问输入流资源。
  • ByteArrayResource: 访问字节数组资源。

这些实现类为不同的资源类型提供了便捷的访问方式,使客户端程序能够轻松地访问各种资源。

二. 源码分析


通过跟踪 ClassPathXmlApplicationContext 对象的创建过程,可以深入了解 Spring 如何使用 Resource 接口及其实现类来实现策略模式。

策略模式的优势在于,当 Spring 应用需要访问资源时,并不需要直接使用 Resource 实现类,而是通过 ApplicationContext 实例的 getResource() 方法来获取资源。ApplicationContext 会负责选择合适的 Resource 实现类,即确定具体的资源访问策略,从而将应用程序与具体的资源访问策略分离,体现了策略模式的优势。

1 //1. 根据传入的配置文件地址,创建容器对象 ClassPathXmlApplicationContext
2 public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
3 this(new String[] {configLocation}, true, null);
4 }

2 //2. 1中代码调用到此处,此处调用父类构造函数 ClassPathXmlApplicationContext
3 public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
4 super(parent);
5 setConfigLocations(configLocations);
6 if (refresh) {
7 refresh();
8 }
9 }

1 //3. 2中代码一步步调用到此处 AbstractApplicationContext
2 public AbstractApplicationContext(ApplicationContext parent) {
3 this();
4 setParent(parent);
5 }

1 //4. 3中代码调用此处 AbstractApplicationContext
2 public AbstractApplicationContext() {
3 this.resourcePatternResolver = getResourcePatternResolver();
4 }

1 //5. 返回能将1中传入的configLocation转换成Resource对象的ResourcePatternResolver AbstractApplicationContext
2 protected ResourcePatternResolver getResourcePatternResolver() {
3 return new PathMatchingResourcePatternResolver(this);
4 }

1 //6. 真正用到策略模式的地方,根据location的内容,决定返回对应的Resource实现,这个过程对客户来说是透明的 DefaultResourceLoader
2 @Override
3 public Resource getResource(String location) {
4 Assert.notNull(location, "Location must not be null");
5
6 for (ProtocolResolver protocolResolver : this.protocolResolvers) {
7 Resource resource = protocolResolver.resolve(location, this);
8 if (resource != null) {
9 return resource;
10 }
11 }
12
13 if (location.startsWith("/")) {
14 return getResourceByPath(location);
15 }
16 else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
17 return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
18 }
19 else {
20 try {
21 URL url = new URL(location);
22 return new UrlResource(url);
23 }
24 catch (MalformedURLException ex) {
25 return getResourceByPath(location);
26 }
27 }
28 }

参考文献:IBM Developer Works

来源:CSDN 博客


推荐阅读
author-avatar
回音爱Fred
这个家伙很懒,什么也没留下!
Tags | 热门标签
RankList | 热门文章
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有