從今天開始,一步步走上源碼分析的路。剛開始肯定要從簡單著手。我們先從java發展史上最強大的框架——Spring、、、旗下的資源抽象接口Resource開始吧。
我看了好多分析Spring源碼的,每每一開始就是Spring IOC、AOP、BeanFactory這樣的Spring典型模塊,實在看厭了,這些暫且留到以后。我的想法是,分析就分析別人沒分析過的,或者以不同的角度來分析別人分析過的。
可能很多用了Spring多年的程序員對Resource都了解有限,畢竟訪問資源一般是搭建web工程框架的時候的事情。不過了解它也是非常有好處的。
這個接口的作用是可以讓我們更方便操縱底層資源。因為JDK操縱底層資源基本就是 java.net.URL 、java.io.File 、java.util.Properties這些。取資源基本是根據絕對路徑或當前類的相對路徑來取。從類路徑或Web容器上下文中獲取資源的時候也不方便。Resource接口提供了更強大的訪問底層資源的能力。
廢話不多說,看源碼之前先來看一下Resource的類結構。
一、類結構
一、Resource接口
如圖,Resouce接口并不是一個根接口,它繼承了一個簡單的父接口%20InputStreamSource,這個接口只有一個方法,用以返回一個輸入流:
InputStream%20getInputStream()%20throws%20IOException;
來,直接上Resource接口的源碼,中文是我根據英文注釋自己翻譯的,如下:
public%20interface%20Resource%20extends%20InputStreamSource%20{%20%20%20%20boolean%20exists();%20%20%20%20%20%20//%20%20資源是否存在%20%20%20%20boolean%20isReadable();%20%20//%20%20資源是否可讀%20%20%20%20boolean%20isOpen();%20%20%20%20%20%20//%20%20資源所代表的句柄是否被一個stream打開了%20%20%20%20URL%20getURL()%20throws%20IOException;%20%20%20//%20%20返回資源的URL的句柄%20%20%20%20URI%20getURI()%20throws%20IOException;%20%20%20//%20%20返回資源的URI的句柄%20%20%20%20File%20getFile()%20throws%20IOException;%20//%20%20返回資源的File的句柄%20%20%20%20long%20contentLength()%20throws%20IOException;%20%20%20//%20%20資源內容的長度%20%20%20%20long%20lastModified()%20throws%20IOException;%20%20%20%20//%20%20資源最后的修改時間%20%20%20%20Resource%20createRelative(String%20relativePath)%20throws%20IOException;%20%20%20//根據資源的相對路徑創建新資源%20%20%20%20String%20getFilename();%20%20//%20%20資源的文件名%20%20%20%20String%20getDescr/* * Copyright 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.springframework.core.io;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URI;import java.net.URL;import java.net.URLConnection;import org.springframework.util.ResourceUtils;/** * Abstract base class for resources which resolve URLs into File references, * such as {@link UrlResource} or {@link ClassPathResource}. * * <p>Detects the "file" protocol as well as the JBoss "vfs" protocol in URLs, * resolving file system references accordingly. * * @author Juergen Hoeller * @since 3.0 */public abstract class AbstractFileResolvingResource extends AbstractResource { @Override public File getFile() throws IOException { // 通過資源的URL得到資源本身,是文件就返回文件,否則返回描述 URL url = getURL(); if (url.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) { return VfsResourceDelegate.getResource(url).getFile(); } return ResourceUtils.getFile(url, getDescription()); } @Override protected File getFileForLastModifiedCheck() throws IOException { //從<壓縮文件地址>中獲取文件 URL url = getURL(); if (ResourceUtils.isJarURL(url)) { URL actualUrl = ResourceUtils.extractJarFileURL(url); if (actualUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) { return VfsResourceDelegate.getResource(actualUrl).getFile(); } return ResourceUtils.getFile(actualUrl, "Jar URL"); } else { return getFile(); } } protected File getFile(URI uri) throws IOException { // 通過資源uri獲取文件 if (uri.getScheme().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) { return VfsResourceDelegate.getResource(uri).getFile(); } return ResourceUtils.getFile(uri, getDescription()); } @Override public boolean exists() { //判斷資源是否存在,如果是文件Url,直接獲取文件判斷,否則,建立連接來判斷。 try { URL url = getURL(); if (ResourceUtils.isFileURL(url)) { // Proceed with file system resolution... return getFile().exists(); } else { // Try a URL connection content-length header... URLConnection con = url.openConnection(); ResourceUtils.useCachesIfNecessary(con); HttpURLConnection httpCon = (con instanceof HttpURLConnection ? (HttpURLConnection) con : null); if (httpCon != null) { httpCon.setRequestMethod("HEAD"); int code = httpCon.getResponseCode(); if (code == HttpURLConnection.HTTP_OK) { return true; } else if (code == HttpURLConnection.HTTP_NOT_FOUND) { return false; } } if (con.getContentLength() >= 0) { return true; } if (httpCon != null) { // no HTTP OK status, and no content-length header: give up httpCon.disconnect(); return false; } else { // Fall back to stream existence: can we open the stream? InputStream is = getInputStream(); is.close(); return true; } } } catch (IOException ex) { return false; } } @Override public boolean isReadable() { // 是否可讀 try { URL url = getURL(); if (ResourceUtils.isFileURL(url)) { // Proceed with file system resolution... File file = getFile(); return (file.canRead() && !file.isDirectory()); } else { return true; } } catch (IOException ex) { return false; } } @Override public long contentLength() throws IOException { URL url = getURL(); if (ResourceUtils.isFileURL(url)) { // Proceed with file system resolution... return getFile().length(); } else { // Try a URL connection content-length header... URLConnection con = url.openConnection(); ResourceUtils.useCachesIfNecessary(con); if (con instanceof HttpURLConnection) { ((HttpURLConnection) con).setRequestMethod("HEAD"); } return con.getContentLength();
新聞熱點
疑難解答