spring source code (4) -- ClassPathResource

Posted by uniflare on Tue, 31 Dec 2019 07:22:42 +0100

In Java, resources from different sources are abstracted into URLs, and different resources ("file,http,jar") are processed by registering different handlers. By default, URLs do not have handlers relative to resources such as "classpath:" or ServletContext. Therefore, spring implements its own abstract structure for resources used internally: Resource interface to encapsulate the underlying resources.

The resource interface provides the transformation of File, url and uri. Provide getDescription to print information in error handling.

Class inheritance hierarchy:

Class name Effect
InputStreamSource The method of getting InputStream is defined
Resource The method of getting resource attributes is defined
AbstractResource Implement the Resource method
AbstractFileResolvingResource Overriding the AbstractResource method
ClassPathResource The method of InputStreamSource is emphasized

Three member variables are defined:

    private final String path;
    private ClassLoader classLoader;
    private Class<?> clazz;

Construction method

    public ClassPathResource(String path) {
        this(path, (ClassLoader)null);
    }

    public ClassPathResource(String path, ClassLoader classLoader) {
        Assert.notNull(path, "Path must not be null");
        String pathToUse = StringUtils.cleanPath(path);
        if(pathToUse.startsWith("/")) {
            pathToUse = pathToUse.substring(1);
        }

        this.path = pathToUse;
        this.classLoader = classLoader != null?classLoader:ClassUtils.getDefaultClassLoader();
    }

    public ClassPathResource(String path, Class<?> clazz) {
        Assert.notNull(path, "Path must not be null");
        this.path = StringUtils.cleanPath(path);
        this.clazz = clazz;
    }
    protected ClassPathResource(String path, ClassLoader classLoader, Class<?> clazz) {
        this.path = StringUtils.cleanPath(path);
        this.classLoader = classLoader;
        this.clazz = clazz;
    }

Core approach:

//Get the input stream of the file resource. The path is based on the classpath
 public InputStream getInputStream() throws IOException {
        InputStream is;
        if(this.clazz != null) {
            is = this.clazz.getResourceAsStream(this.path);
        } else if(this.classLoader != null) {
            is = this.classLoader.getResourceAsStream(this.path);
        } else {
            is = ClassLoader.getSystemResourceAsStream(this.path);
        }

        if(is == null) {
            throw new FileNotFoundException(this.getDescription() + " cannot be opened because it does not exist");
        } else {
            return is;
        }
    }
//Create related resources based on the location of the current file
public Resource createRelative(String relativePath) {
        String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);
        return this.clazz != null?new ClassPathResource(pathToUse, this.clazz):new ClassPathResource(pathToUse, this.classLoader);
    }
//Get description of file location
 public String getDescription() {
        StringBuilder builder = new StringBuilder("class path resource [");
        String pathToUse = this.path;
        if(this.clazz != null && !pathToUse.startsWith("/")) {
            builder.append(ClassUtils.classPackageAsResourcePath(this.clazz));
            builder.append('/');
        }

        if(pathToUse.startsWith("/")) {
            pathToUse = pathToUse.substring(1);
        }

        builder.append(pathToUse);
        builder.append(']');
        return builder.toString();
    }

Topics: Java Spring