AbstractResource实现了Resource的大部分方法,下面逐个方法解析一下:
1.
/**
* This implementation checks whether a File can be opened,
* falling back to whether an InputStream can be opened.
* This will cover both directories and content resources.
*/
public boolean exists() {
// Try file existence: can we find the file in the file system?
try {
return getFile().exists();
}
catch (IOException ex) {
// Fall back to stream existence: can we open the stream?
try {
InputStream is = getInputStream();
is.close();
return true;
}
catch (Throwable isEx) {
return false;
}
}
}
注释的意思是这方法主要用来判断所请求资源是否存在(包括当前资源和本地主机上的路径资源,不存在包括资源有无和是否可以被打开)
方法内部,return getFile().exists();getFile()方法抛出了一个受查异常FileNotFoundException(getDescription() + " cannot be resolved to absolute file path");发生异常抛出后会进入本方法的catch块,关闭Inputstream如果没有成功返返回一个false,返回外层异常,抛出一个笼统的IOException。
第二个方法
/**
* This implementation always returns <code>true</code>.
*/
public boolean isReadable() {
return true;
}
注释写着本方法永远返回true,小心求证,该类的直接父接口Resource,关于exists()方法如下:
/**
* Return whether the contents of this resource can be read,
* e.g. via {@link #getInputStream()} or {@link #getFile()}.
* <p>Will be <code>true</code> for typical resource descriptors;
* note that actual content reading may still fail when attempted.
* However, a value of <code>false</code> is a definitive indication
* that the resource content cannot be read.
* @see #getInputStream()
*/
boolean isReadable();
看了注释,里面的 note that actual content reading may still fail when attempted.这句话是说不管怎样这个方法无法控制都容易失败,Juergen Hoeller肯能觉得io的决定因素很多,所以就懒得实现这个方法了吧,在讨论方法中一律返回true。
第三个方法:
/**
* This implementation always returns <code>false</code>.
*/
public boolean isOpen() {
return false;
}
和上面的方法不同,永远返回false,用上一个方法的结局思路看Resource接口中的方法注释。
/**
* Return whether this resource represents a handle with an open
* stream. If true, the InputStream cannot be read multiple times,
* and must be read and closed to avoid resource leaks.
* <p>Will be <code>false</code> for typical resource descriptors.
*/
boolean isOpen();
看到了,方法说如果输入流打开,就不能使用,必须要关闭避免资源泄露。作者假定一切顺利,如果发生异常,可能会在别的方法内处理。
4.第四个方法
/**
* This implementation throws a FileNotFoundException, assuming
* that the resource cannot be resolved to a URL.
*/
public URL getURL() throws IOException {
throw new FileNotFoundException(getDescription() + " cannot be resolved to URL");
}
假设发生错误就抛出异常。
5.第五个方法
/**
* This implementation builds a URI based on the URL returned
* by {@link #getURL()}.
*/
public URI getURI() throws IOException {
URL url = getURL();
try {
return ResourceUtils.toURI(url);
}
catch (URISyntaxException ex) {
throw new NestedIOException("Invalid URI [" + url + "]", ex);
}
}
这个实现会根据资源描述符建立一个资源定位符,具体分析方法。
URL url = getURL();获取URL();
try {
return ResourceUtils.toURI(url);
}
catch (URISyntaxException ex) {
throw new NestedIOException("Invalid URI [" + url + "]", ex);
}
方法不能完成捕获基本的net包内异常URISyntaxException资源定位符表达式异常,抛出的是Spring的自定义异常,NestedIOException。
6.第六个方法
/**
* This implementation throws a FileNotFoundException, assuming
* that the resource cannot be resolved to an absolute file path.
*/
public File getFile() throws IOException {
throw new FileNotFoundException(getDescription() + " cannot be resolved to absolute file path");
}
这个方法在获得文件错误时抛出文件找不到异常哈哈。
7.第七个方法
/**
* This implementation reads the entire InputStream to calculate the
* content length. Subclasses will almost always be able to provide
* a more optimal version of this, e.g. checking a File length.
* @see #getInputStream()
*/
public long contentLength() throws IOException {
InputStream is = getInputStream();
try {
long size = 0;
byte[] buf = new byte[255];
for (int read = is.read(buf); read != -1;) {
size += read;
}
return size;
}
finally {
try {
is.close();
}
catch (IOException ex) {
}
}
}
这个方法根据以后各种实现getInputStream的类来计算输入的内容长度long。哈哈】
8.第八个方法
/**
* This implementation checks the timestamp of the underlying File,
* if available.
* @see #getFileForLastModifiedCheck()
*/
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;
}
这个方法检查资源的最后修改时间,里面的getFileForLastModifiedCheck()需要一看,如下:
/**
* Determine the File to use for timestamp checking.
* <p>The default implementation delegates to {@link #getFile()}.
* @return the File to use for timestamp checking (never <code>null</code>)
* @throws IOException if the resource cannot be resolved as absolute
* file path, i.e. if the resource is not available in a file system
*/
protected File getFileForLastModifiedCheck() throws IOException {
return getFile();
}
这个图方法调用getFile(),就回去,调用File类中的lastModified(),这个方法解释了一下getFile()抛出异常的情况,两种一个是不是绝对路径抛出,也就是对于系统来说无效的路径。
9.第九个方法
/**
* This implementation throws a FileNotFoundException, assuming
* that relative resources cannot be created for this resource.
*/
public Resource createRelative(String relativePath) throws IOException {
throw new FileNotFoundException("Cannot create a relative resource for " + getDescription());
}
相关资源不能被创建就抛出异常,文件找不到。
10.第十个方法
/**
* This implementation always returns <code>null</code>,
* assuming that this resource type does not have a filename.
*/
public String getFilename() throws IllegalStateException {
return null;
}
这个方法通常返回null,假定资源无名。
11.第十一个方法
/**
* This implementation returns the description of this resource.
* @see #getDescription()
*/
@Override
public String toString() {
return getDescription();
}
调用getDescription();这个方法在哪?在实现类里面,各个实现初始化的时候都会填充description【String】。
12.第十二个方法
/**
* This implementation compares description strings.
* @see #getDescription()
*/
@Override
public boolean equals(Object obj) {
return (obj == this ||
(obj instanceof Resource && ((Resource) obj).getDescription().equals(getDescription())));
}
这个equals方法写的很牛逼!!!!!!!!!!!!判断参数的地址,判断参数的父类(接口也是类),如果是强转,调用description()【实现类实现】,判断描述,调用原始的equals方法。也就是两种情况,就是一个对象,或者描述一致,就认为是一个资源,这种情况我存在疑问,可能框架会限制Resource的单例。。。。
最后一个方法
/**
* This implementation returns the description's hash code.
* @see #getDescription()
*/
@Override
public int hashCode() {
return getDescription().hashCode();
}
简单的返回hashcode。
至此AbstractResource抽象类解释完毕,有一些心得。
最上层接口持有一个公共抽象方法,此方法在其子接口内被反复使用,但会根据具体实现去使用,这样具体实现上有一个抽象类,不去实现这个重要方法,简洁的有一种美感。