Spring source code analysis resource abstract Resource interface

In the API for accessing resources provided by Java, we can specify the location of the resource by URL. The API provided by Java will use different types of URLHandler to handle it, but it also has shortcomings and does not allow everyone to access low-level resources. For example, there is no standard URL implementation for accessing resources from the classpath or ServletContext. Although it is possible to register new handlers for special URL prefixes (similar to existing handlers for prefixes such as http:), this is usually quite complicated, and the URL interface still lacks some required functions, such as checking the pointed resource Does the method exist. Therefore, Spring provides an abstraction for resource access. The Resource interface is used in Spring to access low-level resources. Although the Resource interface is extensively used in Spring, we can also use it as a practical tool class in actual work to allow access Resources become simpler. So I will explain this part separately. The following is the definition of Resource:

public interface InputStreamSource { 
    //查找并加载资源,返回一个从资源中读取的InputStream。每次调用都会返回一个新的InputStream。流的关闭由调用者负责
    InputStream getInputStream() throws IOException; 
} 
public interface Resource extends InputStreamSource { 
    //判断资源是否存在
    boolean exists(); 
    //返回一个布尔值,该值指示此资源是否表示具有开放流的句柄。如果为true,则无法多次读取
    //InputStream,必须只读取一次,然后关闭以避免资源泄漏。对于所有常见的资源实现都将为false,
    //但InputStreamResource除外。
    boolean isOpen(); 
    //返回资源的URL实例
    URL getURL() throws IOException; 
    //返回资源的File实例
    File getFile() throws IOException; 
    //创建一个相对路径的资源
    Resource createRelative(String relativePath) throws IOException; 
    //返回资源名称
    String getFilename(); 
    //返回此资源的说明,在使用该资源时用于错误输出。通常表示完全限定的文件名或资源的实际URL
    String getDescription(); 
}

Resource is an abstraction of resources (such as Spring's xml configuration) in Spring. It is widely used in Spring. It appears as a parameter type when many methods need to use resources (such as the construction method in many implementations of ApplicationContext). The string creates Resource in the constructor, and Resource will select the appropriate implementation to load the resource based on the string. We will explain how Spring loads resources later, so I won't explain it here.

What we need to pay attention to is that Resource does not implement any functions, it just abstracts the functions that may be used into Resource. For example, its implementation of UrlResource wraps a URL and uses the wrapped URL to complete its work. In addition, Spring provides Resource implementations that access almost any resource. The following is the class diagram of Resource implementation.

The hierarchical structure diagram of the above class is all the implementations of Resource, including URL, classpath, Context, FIle, etc. Below we introduce some of the implementations.

UrlResource encapsulates java.net.URL, and can be used to access any object that is usually accessible via URL, such as File, HTTP, FTP, etc. All URLs have a standardized string representation, so that the type of resource can be indicated based on the given string. This includes file: used to access the file system path, http: used to access resources through the http protocol, ftp: used to access resources through ftp, and so on.

 ClassPathResource represents the resource that should be obtained from the class path. It uses the thread context class loader, a given class loader, or a given class to load resources. If the classpath resource resides in the file system, instead of the classpath resource that resides in the jar and has not been extended to the file system (through a servlet engine or other environment), it supports the parsing of java.io.File.

 FileSystemResource is a Resource implementation based on java.io.File operations, and it supports File and URL solutions.

ServletContextResource is the Resource implementation of ServletContext resources, which treats the relative path as the root directory of the web application. It always supports streaming access and URL access, but when the web application is archived and the resource is actually located on the file system, only java.io.File access is allowed. Whether it is in the file system or directly accessed from JAR or other places (such as DB) (this is conceivable) actually depends on the Servlet container

InputStreamResource is the implementation of the Resource of a given InputStream. This method is used only when there is no specific resource implementation applicable. When possible, we should prefer ByteArrayResource or file-based Resource implementation. Different from other Resource implementations, this is a descriptor of an opened resource, so it returns true from isOpen(). Therefore, if you need to save the resource descriptor somewhere, or need to read a stream multiple times, please use other Resource implementations, such as ByteArrayResource.

ByteArrayResource This is the implementation of Resource for a given byte array. It creates a ByteArrayInputStream for the given byte array. It is very useful for loading content from any given byte array. Instead of using InputStreamResource, which can only be read once.

Earlier we introduced several different resource implementations, so how does Spring load Resources? Below we introduce how Spring loads Resource. Resource loading in Spring is abstracted as the ResourceLoader interface, which provides a getResource method to return a Resource instance, which is defined as follows:

public interface ResourceLoader { 
    Resource getResource(String location); 
}

All application contexts implement the ResourceLoader interface, such as ClassPathXmlApplicationContext, FileSystemXmlApplicationContext, WebApplicationContext, etc. We can obtain a Resource instance through these implementations. We use ClassPathXmlApplicationContext as an example. The class hierarchy diagram and code are as follows:

Resource template = ctx.getResource("some/resource/path/myTemplate.txt");

In the above code, if ctx is a ClassPathXmlApplicationContext instance, it will return a ClassPathResource; if ctx is a FileSystemXmlApplicationContext instance, it will return a FileSystemResource; if it is a WebApplicationContext, it will return a ServletContextResource and so on. You can also get the type of the specified Resource of the Resource. At this time, the Resource implementation of the corresponding type will be returned. The code is as follows:

Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt"); 
Resource template = ctx.getResource("file:///some/resource/path/myTemplate.txt");
Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt"); 

Earlier we said that all application contexts implement ResourceLoader, and we can obtain ResourceLoader instances through it. In addition, we can also obtain ResourceLoader instances through the ResourceLoaderAware interface, which is defined as follows:

public interface ResourceLoaderAware { 
    void setResourceLoader(ResourceLoader resourceLoader); 
}

When a class implements the ResourceLoaderAware interface, and the class is managed by the Spring container, the class will be treated as ResourceLoaderAware by the application context, and then call setResourceLoader(ResourceLoader) to provide a ResourceLoader instance. In fact, many internal implementations of Spring can be used Provided through this program, for example, ApplicationContextAware will provide an ApplicationContext instance, the usage of this class will not be introduced here, you can refer to the blog: Use of Aware interface in Spring-ApplicationContextAware and BeanNameAware .

In addition, we can also automatically inject a Resource instance through Bean. If we have a field of Resource type in Bean, we can inject it through Bean. Examples are as follows:

<bean id="myBean" class="..."> 
    <property name="template" value="some/resource/path/myTemplate.txt"/> 
</bean> 

Because the resources configured above do not have a prefix, the application context itself will act as ResourceLoader, and the resource itself will be loaded via ClassPathResource, FileSystemResource or ServletContextResource, depending on the context. Of course, we can also specify specific types, examples are as follows:

<bean id="myBean" class="..."> 
    <property name="template" value="file:///some/resource/path/myTemplate.txt"/> 
</bean> 

The application context constructor (for a specific application context type) usually uses a string or an array of strings as the location path of the resource (such as the XML file that constitutes the context definition). When such a location path has no prefix, the specific resource type constructed from the path and used to load the bean definition depends on and is suitable for the specific application context. For example, if you create a ClassPathXmlApplicationContext as follows:

ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");

The above method will load resources from the classpath and use ClassPathResource, but if you create a FileSystemXmlApplicationContext, it will be loaded from the file system location. The following example is relative to the current working directory.

ApplicationContext ctx  =  new FileSystemXmlApplicationContext("conf/appContext.xml");

If we add a prefix or URL to the incoming parameters, the default type will be overwritten. For example, the following example will load resources from the classpath:

ApplicationContext ctx =  new FileSystemXmlApplicationContext("classpath:conf/appContext.xml"); 

The resource path in the application context constructor value can be a simple path (as shown in shownabove), which has a one-to-one mapping with the target resource, or it can include a special "classpath*:" prefix and/or internal Ant style The regular expression (use Spring's PathMatcher utility for matching). The following is an example of Ant-style resource path:

/WEB-INF/*-context.xml 
com/mycompany/**/applicationContext.xml 
file:C:/some/path/*-context.xml 
classpath:com/mycompany/**/applicationContext.xml

 

Guess you like

Origin blog.csdn.net/wk19920726/article/details/108782929