InputStreamResource 的 getInputStream方法在其他 Resource中的实现

概述

Resource 是 Spring框架中统一管理底层资源的接口。

1、ClassPathResource

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.core.io;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

public class ClassPathResource extends AbstractFileResolvingResource {
    // 文件路径,例如 application-context.xml文件
    private final String path;
    // 类加载器
    @Nullable
    private ClassLoader classLoader;
    @Nullable
    private Class<?> clazz;

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

    // 构造函数
    public ClassPathResource(String path, @Nullable 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;
        // 指定类加载器,如果没有传类加载器,则用默认的类加载器,翻看源码是:Thread.currentThread().getContextClassLoader()
        this.classLoader = classLoader != null?classLoader:ClassUtils.getDefaultClassLoader();
    }

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

    /** @deprecated */
    @Deprecated
    protected ClassPathResource(String path, @Nullable ClassLoader classLoader, @Nullable Class<?> clazz) {
        this.path = StringUtils.cleanPath(path);
        this.classLoader = classLoader;
        this.clazz = clazz;
    }

    // 获取配置文件路径
    public final String getPath() {
        return this.path;
    }
    // 获取类加载器
    @Nullable
    public final ClassLoader getClassLoader() {
        return this.clazz != null?this.clazz.getClassLoader():this.classLoader;
    }
    // 判断文件是否存在
    public boolean exists() {
        return this.resolveURL() != null;
    }

    @Nullable
    protected URL resolveURL() {
        return this.clazz != null?this.clazz.getResource(this.path):(this.classLoader != null?this.classLoader.getResource(this.path):ClassLoader.getSystemResource(this.path));
    }
    // 此方法继承自InputStreamSource,ClassPathResource实现了具体逻辑
    // 主要就是通过类加载器加载配置文件到内存 InputStream中
    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;
        }
    }

    public URL getURL() throws IOException {
        URL url = this.resolveURL();
        if(url == null) {
            throw new FileNotFoundException(this.getDescription() + " cannot be resolved to URL because it does not exist");
        } else {
            return url;
        }
    }

    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);
    }

    @Nullable
    public String getFilename() {
        return StringUtils.getFilename(this.path);
    }

    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();
    }

    public boolean equals(@Nullable Object other) {
        if(this == other) {
            return true;
        } else if(!(other instanceof ClassPathResource)) {
            return false;
        } else {
            ClassPathResource otherRes = (ClassPathResource)other;
            return this.path.equals(otherRes.path) && ObjectUtils.nullSafeEquals(this.classLoader, otherRes.classLoader) && ObjectUtils.nullSafeEquals(this.clazz, otherRes.clazz);
        }
    }

    public int hashCode() {
        return this.path.hashCode();
    }
}

如以上代码中注释的,ClassPathResource 初始化时主要保存 classpath路径下配置文件路径,选择类加载器,然后在继承自 InputStreamResource 的方法 getInputStream中 通过 类加载器加载配置文件到内存(InputStream)中,供Reader使用。

2、FileSystemResource

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.core.io;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

public class FileSystemResource extends AbstractResource implements WritableResource {
    // 资源路径
    private final String path;
    // 资源路径File
    @Nullable
    private final File file;
    private final Path filePath;

    public FileSystemResource(String path) {
        Assert.notNull(path, "Path must not be null");
        this.path = StringUtils.cleanPath(path);
        this.file = new File(path);
        this.filePath = this.file.toPath();
    }

    public FileSystemResource(File file) {
        Assert.notNull(file, "File must not be null");
        this.path = StringUtils.cleanPath(file.getPath());
        this.file = file;
        this.filePath = file.toPath();
    }

    public FileSystemResource(Path filePath) {
        Assert.notNull(filePath, "Path must not be null");
        this.path = StringUtils.cleanPath(filePath.toString());
        this.file = null;
        this.filePath = filePath;
    }

    public FileSystemResource(FileSystem fileSystem, String path) {
        Assert.notNull(fileSystem, "FileSystem must not be null");
        Assert.notNull(path, "Path must not be null");
        this.path = StringUtils.cleanPath(path);
        this.file = null;
        this.filePath = fileSystem.getPath(this.path, new String[0]).normalize();
    }

    public final String getPath() {
        return this.path;
    }

    public boolean exists() {
        return this.file != null?this.file.exists():Files.exists(this.filePath, new LinkOption[0]);
    }

    public boolean isReadable() {
        return this.file != null?this.file.canRead() && !this.file.isDirectory():Files.isReadable(this.filePath) && !Files.isDirectory(this.filePath, new LinkOption[0]);
    }
    // 继承自 InputStreamResource,加载并获取配置文件的流
    public InputStream getInputStream() throws IOException {
        try {
            // 之前版本是直接用 FileInputStream(this.file);5.0版本变成NIO方式加载,待研究
            return Files.newInputStream(this.filePath, new OpenOption[0]);
        } catch (NoSuchFileException var2) {
            throw new FileNotFoundException(var2.getMessage());
        }
    }

    public boolean isWritable() {
        return this.file != null?this.file.canWrite() && !this.file.isDirectory():Files.isWritable(this.filePath) && !Files.isDirectory(this.filePath, new LinkOption[0]);
    }

    public OutputStream getOutputStream() throws IOException {
        return Files.newOutputStream(this.filePath, new OpenOption[0]);
    }

    public URL getURL() throws IOException {
        return this.file != null?this.file.toURI().toURL():this.filePath.toUri().toURL();
    }

    public URI getURI() throws IOException {
        return this.file != null?this.file.toURI():this.filePath.toUri();
    }

    public boolean isFile() {
        return true;
    }

    public File getFile() {
        return this.file != null?this.file:this.filePath.toFile();
    }

    public ReadableByteChannel readableChannel() throws IOException {
        try {
            return FileChannel.open(this.filePath, new OpenOption[]{StandardOpenOption.READ});
        } catch (NoSuchFileException var2) {
            throw new FileNotFoundException(var2.getMessage());
        }
    }

    public WritableByteChannel writableChannel() throws IOException {
        return FileChannel.open(this.filePath, new OpenOption[]{StandardOpenOption.WRITE});
    }

    public long contentLength() throws IOException {
        if(this.file != null) {
            long length = this.file.length();
            if(length == 0L && !this.file.exists()) {
                throw new FileNotFoundException(this.getDescription() + " cannot be resolved in the file system for checking its content length");
            } else {
                return length;
            }
        } else {
            try {
                return Files.size(this.filePath);
            } catch (NoSuchFileException var3) {
                throw new FileNotFoundException(var3.getMessage());
            }
        }
    }

    public long lastModified() throws IOException {
        if(this.file != null) {
            return super.lastModified();
        } else {
            try {
                return Files.getLastModifiedTime(this.filePath, new LinkOption[0]).toMillis();
            } catch (NoSuchFileException var2) {
                throw new FileNotFoundException(var2.getMessage());
            }
        }
    }

    public Resource createRelative(String relativePath) {
        String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);
        return this.file != null?new FileSystemResource(pathToUse):new FileSystemResource(this.filePath.getFileSystem(), pathToUse);
    }

    public String getFilename() {
        return this.file != null?this.file.getName():this.filePath.getFileName().toString();
    }

    public String getDescription() {
        return "file [" + (this.file != null?this.file.getAbsolutePath():this.filePath.toAbsolutePath()) + "]";
    }

    public boolean equals(@Nullable Object other) {
        return this == other || other instanceof FileSystemResource && this.path.equals(((FileSystemResource)other).path);
    }

    public int hashCode() {
        return this.path.hashCode();
    }
}
发布了178 篇原创文章 · 获赞 47 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/ruanhao1203/article/details/103447084
今日推荐