目录
概述
1、ClassPathResource
2、FileSystemResource
概述
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;// 类加载器@Nullableprivate ClassLoader classLoader;@Nullableprivate 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 */@Deprecatedprotected 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;}// 获取类加载器@Nullablepublic final ClassLoader getClassLoader() {return this.clazz != null?this.clazz.getClassLoader():this.classLoader;}// 判断文件是否存在public boolean exists() {return this.resolveURL() != null;}@Nullableprotected 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);}@Nullablepublic 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@Nullableprivate 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();}
}