Class.getResource()有/没有/的区别:有/ 代表从classpath根目录/ 没有path代表当前文件所在路径
URL resourc1 = GridFsTest.class.getResource("");
URL resource2 = GridFsTest.class.getResource("/");
ClassLoader.getResource()不能以“/”开头
//ClassLoader.getResource() 统一从classPath下加载,所以不能以“/”开头
URL resource = GridFsTest.class.getClassLoader().getResource(""); //classpath 根目录
URL resource3 = GridFsTest.class.getClassLoader().getResource("/");
ps : Class.getResource()最终也是调用的ClassLoader
Class.getResource()执行流程分析
public java.net.URL getResource(String name) {
// 转换名称,是否以/开头
name = resolveName(name);
// 这里获取的是AppclassLoader 显然不是系统类
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
// 如果是系统加载的类,走这里
return ClassLoader.getSystemResource(name);
}
// 这里之后的过程详见下图
return cl.getResource(name);
}
getResource 源码如下,详细解释见下面图文
public URL getResource(String name) {
URL url;
if (parent != null) {
url = parent.getResource(name);
} else {
url = getBootstrapResource(name);
}
if (url == null) {
url = findResource(name);
}
return url;
}
步骤1,获取父类加载器ExtClassLoader ,ExtClassloader 父亲节点为空,于是会去bootstrap启动器加载的目录下寻找该资源(步骤2),也就是你jdk安装目录下/jre/lib目录下,如果还没有找到则去调用findResource方法(步骤4),在ExtClassloader所管辖的目录下查找资源,也就是你jdk安装目录下的/jre/lib/ext目录下,如果这个时候还没有找到资源,则进入步骤5,轮到AppClassloader加载资源,AppClassloader会从项目classpath目录下查找。
整个查找资源的方式体现了双亲委派。