Spring ResourceLoader-DefaultResourceLoader从classpath加载文件

27 篇文章 0 订阅

首先看一段代码 ,以下这段代是码是从classpath中加载资源
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
Resource resource = resourceLoader.getResource("classpath:test/a/");
URL url = resource.getURL();
... //根据url读取文件
org.springframework.core.io.DefaultResourceLoader.getResource(String)源码如下:
	public Resource getResource(String location) {
		Assert.notNull(location, "Location must not be null");

		for (ProtocolResolver protocolResolver : this.protocolResolvers) {
			Resource resource = protocolResolver.resolve(location, this);
			if (resource != null) {
				return resource;
			}
		}

		if (location.startsWith("/")) {
			return getResourceByPath(location);
		}
		else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
			return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
		}
		else {
			try {
				// Try to parse the location as a URL...
				URL url = new URL(location);
				return new UrlResource(url);
			}
			catch (MalformedURLException ex) {
				// No URL -> resolve as resource path.
				return getResourceByPath(location);
			}
		}
	}


代码中红色标记处是处理从classpath中加载资源的,这里创建一个个ClassPathResource实例,第二个参数是设置一个classloader, 再看 org.springframework.core.io.DefaultResourceLoader.getClassLoader方法:
@Override
public ClassLoader getClassLoader() {
return (this.classLoader != null ? this.classLoader : ClassUtils.getDefaultClassLoader());
}
我们没有对this.classLoader赋值,默认为null, 继续看ClassUtils.getDefaultClassLoader()方法:
	public static ClassLoader getDefaultClassLoader() {
		ClassLoader cl = null;
		try {
			cl = Thread.currentThread().getContextClassLoader();
		}
		catch (Throwable ex) {
			// Cannot access thread context ClassLoader - falling back...
		}
		if (cl == null) {
			// No thread context class loader -> use class loader of this class.
			cl = ClassUtils.class.getClassLoader();
			if (cl == null) {
				// getClassLoader() returning null indicates the bootstrap ClassLoader
				try {
					cl = ClassLoader.getSystemClassLoader();
				}
				catch (Throwable ex) {
					// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
				}
			}
		}
		return cl;
	}


红色标记处,显示使用ClasspathResource使用的ClassLoader为: Thread.currentThread().getContextClassLoader();
当前线程的ContextClassLoader, 这个和当前程序运行在哪种容器(或环境)有关了
比如运行在Tomcat8.5.6容器中,ContextClassLoader为: org.apache.catalina.loader.ParallelWebappClassLoader


再回过头来看,org.springframework.core.io.ClassPathResource.getURL()方法:
public URL getURL() throws IOException {
URL url = resolveURL();
if (url == null) {
throw new FileNotFoundException(getDescription() + " cannot be resolved to URL because it does not exist");
}
return url;
}
继续看,org.springframework.core.io.ClassPathResource.resolveURL():
protected URL resolveURL() {
if (this.clazz != null) {
return this.clazz.getResource(this.path);
}
else if (this.classLoader != null) {
return this.classLoader.getResource(this.path);
}
else {
return ClassLoader.getSystemResource(this.path);
}
}
方法实现中
如果设置了clazz调用clazz.getResource,否则
如果设置了classLoader调用classLoader.getResource,否则
使用 ClassLoader.getSystemResource
还是以我们运行在Tomcat8.5.6为例,就会调用 org.apache.catalina.loader.ParallelWebappClassLoader.getResource,通过tomcat文档 https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html 看到
Therefore, from the perspective of a web application, class or resource loading looks in the following repositories, in this order:
  • Bootstrap classes of your JVM
  • /WEB-INF/classes of your web application
  • /WEB-INF/lib/*.jar of your web application
  • System class loader classes (described above)
  • Common class loader classes (described above)
所以资源加载顺序为
1. WEB-INF\classes  
2.classpath
3. $CATALINA_BASE/lib

说到底spring的ResouceLoader就是根据我们设置的ClassLoader来进行资源加载
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值