Spring Source Analysis--Resource access tool resource interface and abstract class analysis

Source: Internet
Author: User
Tags file url readable jboss

From today onwards, step by step into the path of source analysis. At first, we must start from the simple. Let's start with the most powerful framework in Java history,--spring 、、、 Resources Abstraction Interface resource.

I read a lot of analysis spring source, often at the beginning is Spring IOC, AOP, beanfactory such a spring typical module, really tired, these leave to later. My idea is that analysis is an analysis of other people have not analyzed, or in different ways to analyze the analysis of others.

There may be many years of use of spring programmers have limited knowledge of resource, after all, access to resources is generally the time to build a Web engineering framework. But it's also very good to know about it.

The purpose of this interface is to make it easier for us to manipulate the underlying resources. Because the JDK manipulates the underlying resources basically is Java.net.URL, Java.io.File, java.util.Properties these. The resource fetch is basically based on the absolute path or the relative path of the current class. It is also inconvenient to obtain resources from the context of a classpath or Web container. The resource interface provides a more powerful ability to access the underlying resources.

Needless to say, look at the source code before looking at the resource class structure.

First, class structure

First, Resource interface

, the Resouce interface is not a root interface, it inherits a simple parent interface Inputstreamsource, which has only one method to return an input stream:

InputStream getInputStream () throws IOException;

To, directly on the resource interface source code, Chinese is I according to the English annotation own translation, as follows:

Public interface Resource extends Inputstreamsource {    Boolean exists ();  whether the resource exists as a    boolean isreadable ();  whether the resource is readable    boolean isOpen ();  whether the handle represented by the resource is opened by a stream    URL GetURL () throws IOException;  returns a handle to the URL of the resource    URI GetURI () throws IOException;   Returns a handle to the  URI of the resource    file GetFile () throws IOException;//handle  to the file that returns the resource    long ContentLength () throws IOException;  the length of the resource content    long LastModified () throws IOException;  The last modification time of the resource    Resource createrelative (String relativepath) throws IOException;   Creates a new resource based on the relative path of the resource    String getfilename ();  the file name of the resource    String getdescription ();   Description of the resource}

This is nothing to say, go on!

Second, abstract class Abstractresource

For any interface, this direct abstract class is a heavy priority, which condenses most of the public implementations of the interface. Translated as follows:

Public abstract class Abstractresource implements Resource {public Boolean exists () {///determines if the file exists, and if the procedure is called an exception (because the Secur        Itymanager), close the corresponding stream try {return GetFile (). exists ();  } catch (IOException ex) {try {InputStream is = getInputStream ();                getInputStream () method will be overridden by the quilt class, Is.close ();            return true;               } catch (Throwable isex) {return false;    }}} public boolean isreadable () {//returns true directly, readable return true;    public Boolean IsOpen () {//returns false directly, not opened return false; } public URL GetURL () throws IOException {//left subclass rewrite throw new FileNotFoundException (getdescription () +    "Cannot is resolved to URL");        } public URI GetURI () throws IOException {//return URL URL url = GetURL ();     try {return Resourceutils.touri (URL); Returns the URL after formatting is returned} catch (URISyntaxException Ex) {throw new Nestedioexception ("Invalid URI [" + URL + "]", ex); }} public File GetFile () throws IOException {///leave subclass rewrite throw new FileNotFoundException (GetDescription (    ) + "cannot is resolved to absolute file path"); }//This resource content length is actually the byte length of the resource, judged by reading it all over again.    This method calls up a lot of resources Ah!        Public long ContentLength () throws IOException {InputStream is = This.getinputstream ();   Assert.state (IS! = NULL, "Resource input stream must not being null");            Assert try {long size = 0;            byte[] buf = new byte[255];            int read;            while (read = Is.read (BUF))! =-1) {size + = read;        } return size;            } finally {try {is.close (); } catch (IOException ex) {}}} public long LastModified () throws IOException {// Returns the last modified time for a resource 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; }//This is a method that the resource interface does not have, the comment means "return file, give timestamp check", require subclasses to rewrite ... protected File Getfileforlastmodifiedcheck () throws Ioexceptio    n {return getFile (); } public Resource createrelative (String relativepath) throws IOException {//left subclass rewrite throw new Filenotfoundex    Ception ("Cannot create a relative resource for" + getdescription ());    The public String GetFileName () {//returns Null by default (assuming the resource does not have a file name) unless the subclass overrides return null;    } @Override Public String tostring () {///ToString Return File Description return getdescription ();            } @Override public boolean equals (Object obj) {//equals the 2 resource description is the same as return (obj = = This | | (obj instanceof Resource && ((Resource) obj). GetDescription (). Equals (GetDescription ())));   } @Override public int hashcode () {//Return resource Description Hashcode return GetDescription (). Hashcode (); }}

Conclusion:

1, added a method, protected file Getfileforlastmodifiedcheck () throws IOException, the subclass is required to implement, if the subclass is not implemented, then directly return the resource file. The concrete effect of this method, and then look at the implementation class.

2, Method ContentLength (), is a very heavy-weight method, which determines the number of bytes of a resource by reading the resource all over again. A 255-byte buffer array to read. Subclasses are generally rewritten. (Adjust the size of the buffer array?) )

3, GetDescription () is the only non-implementation of this abstract class interface method, left to the subclass to implement, the resource file default equals (), hashcode () through this to judge.

4, Inputstreamsource This ancestor interface of the only method getInputStream () is not implemented, left to the subclass.

Resource sub-interfaces Contextresource and Writableresource

These two interfaces inherit from resource and have all the methods of resource. Where the Contextresource interface adds a method:

String Getpathwithincontext ();  returns the path within the context  

This method enables its implementation class to have the ability to return the current context path.

The Writableresource interface adds 2 methods:

    Boolean iswritable ();  whether it can write    OutputStream getoutputstream () throws IOException;//returns the write stream of the resource

This method enables its implementation class to have the ability to write resources.

Iv. the important abstract class Abstractfileresolvingresource

This abstract class inherits from Abstractresource, overriding most of the methods of Abstractresource.

/*
* Copyright 2002-2011 The original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* You are not a use this file except in compliance with the License.
* Obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable or agreed to writing, software
* Distributed under the License is distributed on a "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 {//through the URL of the resource gets the resource itself, is the file returns the file, otherwise returns a description
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 {//Get files from < zip file address >
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 {//Get files by resource URI
if (Uri.getscheme (). StartsWith (RESOURCEUTILS.URL_PROTOCOL_VFS)) {
Return Vfsresourcedelegate.getresource (URI). GetFile ();
}
Return Resourceutils.getfile (URI, GetDescription ());
}


@Override
public Boolean exists () {///determine if the resource exists, if it is a file URL, directly get the file to judge, otherwise, establish a connection to judge.
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 () {//Is readable
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 ();
}
}

@Override
Public long LastModified () throws IOException {
URL url = GetURL ();
if (Resourceutils.isfileurl (URL) | | Resourceutils.isjarurl (URL)) {
Proceed with file system resolution ...
return super.lastmodified ();
}
else {
Try a URL connection last-modified header ...
URLConnection con = url.openconnection ();
Resourceutils.usecachesifnecessary (con);
if (Con instanceof httpurlconnection) {
((HttpURLConnection) con). Setrequestmethod ("HEAD");
}
return con.getlastmodified ();
}
}


/**
* Inner delegate class, avoiding a hard JBoss VFS API dependency at runtime.
*/
private Static Class Vfsresourcedelegate {

public static Resource getresource (URL url) throws IOException {
return new Vfsresource (Vfsutils.getroot (URL));
}

public static Resource GetResource (Uri uri) throws IOException {
return new Vfsresource (Vfsutils.getroot (URI));
}
}

}

Subclasses of this abstract class need to override the Geturl () method that inherits from Abstractresource. Because most methods rely on this method, the resource is manipulated on the URL.

So when looking at the resource situation, you need to establish a connection based on the URL to view it.

PS: The frame feels most like this, not difficult, the design pattern also uses not much. But there is a kind of big Qiao not work, no front of the feeling, because the code is really very concise use.

Analysis of the source, to a large extent, also exercise their English document reading ability. Share.

Spring Source Analysis--Resource access tool resource interface and abstract class analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.