前些日子看《深入理解javaweb开发》时,看到第一章java的io流,发觉自己对io流真的不是很熟悉。然后看了下JDK1.7中io包的一点点代码,又看了org.springframework.core.io包的一些类和组织方式,当作是学习吧。总结一下。

先挂下spring.core.io包的类图,其中接口是方框表示,抽象类带了abstract前缀,剩下那个两个框重贴的则代表实现类。没怎么划过类图,如果有好的画类图工具请推荐给我。

画得不好的地方就见谅了。注:以下源码匹配的是spring-core-4.1.6Release.jar里面的org.springframework.core.io包。

先看处于最上层的接口,叫InputStreamSource,里面只有一个抽象方法

接下是resources,这个接口我们一般都会用到,贴源码:

public interface Resource extends InputStreamSource {

    boolean exists();//文件是否存在

    boolean isReadable();//是否可读

    boolean isOpen();//资源是否被一个inputstream打开,如果已被打开,则不允许其他流再打开

    URL getURL() throws IOException;//获取资源url路径,当不能以url描述时抛出ioException异常

    URI getURI() throws IOException;//获取资源uri路径,当不能以url描述时抛出ioException异常

    File getFile() throws IOException;//获取file,file在IO流中仅仅是一个指向作用

    long contentLength() throws IOException;//资源的字节长度,可以拿来算资源的大小

    long lastModified() throws IOException;//资源最后修改时间

    Resource createRelative(String relativePath) throws IOException;//根据资源相对路径创建资源

    String getFilename();//返回文件名

    String getDescription();//资源描述

}

后面是abstractResource,这是个挺重要的类,主要是对resource接口的基本实现,

public abstract class AbstractResource implements Resource {

    @Override
public boolean exists() {
//看是否能在硬盘上找到
try {
return getFile().exists();
}
catch (IOException ex) {
// 试一下能不能打开输出流
try {
InputStream is = getInputStream();
is.close();
return true;
}
catch (Throwable isEx) {
return false;
}
}
} /**
* 一般都是可读的,所以默认方法是true
*/
@Override
public boolean isReadable() {
return true;
} /**
* 默认值是false,没有inputStream来读时的默认状态
*/
@Override
public boolean isOpen() {
return false;
} /**
* url这个属性一般只出现在web的IO资源中,网络resource需要override这个方法,其他类型资源敢访问这个方法,抛个异常给他
*/
@Override
public URL getURL() throws IOException {
throw new FileNotFoundException(getDescription() + " cannot be resolved to URL");
} @Override
public URI getURI() throws IOException {
URL url = getURL();
try {
//url可以转成uri,uri不能转url
return ResourceUtils.toURI(url);
}
catch (URISyntaxException ex) {
throw new NestedIOException("Invalid URI [" + url + "]", ex);
}
} /**
* JDK的File类都是返回绝对路径的File,当一个资源没有绝对路径时,抛个异常给它没毛病
*/
@Override
public File getFile() throws IOException {
throw new FileNotFoundException(getDescription() + " cannot be resolved to absolute file path");
} /**
* inputStream读取byte[]字节流,并返回该数组的长度,相当于把文件读了一次
*/
@Override
public long contentLength() throws IOException {
InputStream is = this.getInputStream();
//Assert应该是叫断言
Assert.state(is != null, "resource input stream must not be null");
try {
long size = 0;
byte[] buf = new byte[255];
int read;
while ((read = is.read(buf)) != -1) {
size += read;
}
return size;
}
finally {
try {
//一定要在finally中关闭流
is.close();
}
catch (IOException ex) {
}
}
} /**
* 返回getFileForLastModifiedCheck().lastModified()的值,该职为0L,抛个异常给他没毛病
*/
@Override
public long lastModified() throws IOException {
long lastModified = getFileForLastModifiedCheck().lastModified();
if (lastModified == 0L) {
throw new FileNotFoundException(getDescription() +
" cannot be resolved in the file system for resolving its last-modified timestamp");
}
return lastModified;
} /**
* 调用getFile方法
*/
protected File getFileForLastModifiedCheck() throws IOException {
return getFile();
} /**
* 直接假定相对资源创建不了,再抛个异常给他
*/
@Override
public Resource createRelative(String relativePath) throws IOException {
throw new FileNotFoundException("Cannot create a relative resource for " + getDescription());
} /**
* 又是一个假定,假定filename文件名为null
*/
@Override
public String getFilename() {
return null;
} /**
* 很简单,不解释
*/
@Override
public String toString() {
return getDescription();
} /**
* 判断两文件是否相等
*/
@Override
public boolean equals(Object obj) {
return (obj == this ||
(obj instanceof Resource && ((Resource) obj).getDescription().equals(getDescription())));
} /**
* 返回hashCode
*/
@Override
public int hashCode() {
return getDescription().hashCode();
} }

至于其他实现类其实都是在接口和抽象类的基础上去拓展,所以我并不是读得很仔细,先这样子吧。

小总结:其实为什么要分好几层去继承刚开始我是很不懂的,后面看了源代码和小伙伴的博文后便豁然开朗了。

1.resources是高度抽象的接口,里面是对所有资源文件的具体方法抽象,但是并不是每个资源都有这个抽象里面的所有方法,所以abstractResource对其进行了一般的实现,

对于一些并不是所有的Resources都会有方法,例如非网络资源没有url和uri属性,默认方法就直接抛异常了,简单粗暴。举个栗子,不是所有的动物都会游泳,一只猪想游泳,先抛个异常给猪接着先。

2.resources里面有isOpen(),isReadAble()接口,这是个小技巧吧,类似与模版方法模式的钩子方法,也是很值得我们学习的。

spring源码分析-core.io包里面的类的更多相关文章

  1. Spring源码分析——BeanFactory体系之抽象类、类分析(二)

    上一篇分析了BeanFactory体系的2个类,SimpleAliasRegistry和DefaultSingletonBeanRegistry——Spring源码分析——BeanFactory体系之 ...

  2. Spring源码分析——BeanFactory体系之抽象类、类分析(一)

    上一篇介绍了BeanFactory体系的所有接口——Spring源码分析——BeanFactory体系之接口详细分析,本篇就接着介绍BeanFactory体系的抽象类和接口. 一.BeanFactor ...

  3. Spring源码分析(三)容器核心类

    摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 在上一篇文章中,我们熟悉了容器的基本用法.在这一篇,我们开始分析Spri ...

  4. Spring源码分析(四)容器的基础XmlBeanFactory

    摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 经过Spring源码分析(二)容器基本用法和Spring源码分析(三)容 ...

  5. spring源码分析之spring-core总结篇

    1.spring-core概览 spring-core是spring框架的基石,它为spring框架提供了基础的支持. spring-core从源码上看,分为6个package,分别是asm,cgli ...

  6. Spring源码分析——资源访问利器Resource之实现类分析

    今天来分析Spring的资源接口Resource的各个实现类.关于它的接口和抽象类,参见上一篇博文——Spring源码分析——资源访问利器Resource之接口和抽象类分析 一.文件系统资源 File ...

  7. Spring源码分析之IOC的三种常见用法及源码实现(二)

    Spring源码分析之IOC的三种常见用法及源码实现(二) 回顾上文 我们研究的是 AnnotationConfigApplicationContext annotationConfigApplica ...

  8. spring源码分析(二)Aop

    创建日期:2016.08.19 修改日期:2016.08.20-2016.08.21 交流QQ:992591601 参考资料:<spring源码深度解析>.<spring技术内幕&g ...

  9. 框架-spring源码分析(一)

    框架-spring源码分析(一) 参考: https://www.cnblogs.com/heavenyes/p/3933642.html http://www.cnblogs.com/BINGJJF ...

随机推荐

  1. Mac 切换到行首和行末的方法

    苹果笔记本没有home键和end键 但是使用 command + 方向键左键可以回到行首, command + 方向键右键可以去到行末

  2. PHP之旅5 php的函数

    函数的结构 php的函数和其他语言的函数基本类似,和C语言比较的话主要区别在于php是一个弱语言,对类型不敏感,在函数的表现上就是,php函数没有类型定义,不像语言即使无参也要定义为void,而且不管 ...

  3. Java内存模型Cookbook

    前言 指令重排 内存屏障 多处理器 指南 前言 这是一篇用于说明在JSR-133中制定的新Java内存模型(JMM)的非官方指南. 这篇指南提供了在最简单的背景下各种规则存在的原因,而不是这些规则在指 ...

  4. 理解JavaScript的数值型数据类型

    分享一些在JavaScript中遇到的一些实用的技巧. 理解JavaScript的数值型数据类型 JavaScript的数值型数据类型只有一种:number.即不管是整数还是浮点数,JavaScrip ...

  5. DIV居中的几种方法

    1. body{ text-align:center; } 缺点:body内所有内容一并居中 2. .center{ position: fixed; left: 50%; } 缺点:需要设置posi ...

  6. java --Method

    MethodDemo class MethodDemo { public static void main(String[] args) { //调用自定义的方法. draw(4,5); draw(8 ...

  7. 【转载】 C#中数组、ArrayList和List三者的区别

    原文地址:http://blog.csdn.net/zhang_xinxiu/article/details/8657431 在C#中数组,ArrayList,List都能够存储一组对象,那么这三者到 ...

  8. 剑指offer四十六之孩子们的游戏(圆圈中最后剩下的数,约瑟夫环问题)

    一.题目 每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此.HF作为牛客的资深元老,自然也准备了一些小游戏.其中,有个游戏是这样的:首先,让小朋友们围成一个大圈.然后,他随机指 ...

  9. 关于MyBatis的工作流程和与JDBC的比较与Hibernate的比较

    一.传统的JDBC的方式 1.从一个jdbc程序开始 public static void main(String[] args) { Connection connection = null; Pr ...

  10. github的本地配置和项目创建

    之前完成了github的安装和账号的注册,接下来要进行项目的创建和本地代码仓库的建立 1.创建项目 2.填写项目相关信息 注意:在给项目起名时,尽量起一些有意义的名字,否则会被管理员删除.因为服务器上 ...