====》getResource方法是得到文件路径的函数。
获取文件的路径,使用时主要是两种方法, 一个是字节码文件Class类, 另一个是ClassLoader类加载器
使用Class类时有两种使用方式:
1、不使用"/" 这就是具体该类的路径
2、使用"/" 获取到的是classpath路径
ClassLoader类
1、没有"/"的写法, 直接写文件名获取到的就是classpath路径
其实如果读取class下面的这里就用:
PropertiesUtil.class.getClassLoader().getResource("").getPath()获取就可以。
System.out.println(PropertiesUtil.class.getResource("").getPath()); -->PropertiesUtil.class类所在的位置
System.out.println(PropertiesUtil.class.getResource("/").getPath()); -->classpath的路径
System.out.println(PropertiesUtil.class.getClassLoader().getResource("").getPath());-->classpath的路径
System.out.println(PropertiesUtil.class.getClassLoader().getResource("/")); -->classpath的路径
一、Class.getResource源码解析
看下具体例子:
看下System.out.println(PropertiesUtil.class.getResource("").getPath());的调用。
方法getResource("")的源码:
public java.net.URL getResource(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0(); // 获取加载该Class的ClassLoader
if (cl==null) {//如果加载该Class的ClassLoader为null,则表示这是一个系统class
// A system class.
return ClassLoader.getSystemResource(name);
}
return cl.getResource(name); /调用ClassLoader的getResource方法
}
下面是ClassLoader的getResource方法
public java.net.URL getResource(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0(); // 获取加载该Class的ClassLoader
if (cl==null) {//如果加载该Class的ClassLoader为null,则表示这是一个系统class
// A system class.
return ClassLoader.getSystemResource(name);
}
return cl.getResource(name); /调用ClassLoader的getResource方法
}
下面是ClassLoader的getResource方法
public URL getResource(String name) {
URL url;
if (parent != null) { //这里的parent为sun.misc.Launcher$ExtClassLoader@7d4793a8
url = parent.getResource(name);//这里是一个递归调用,再次进入之后parent为null
} else {
url = getBootstrapResource(name);//到达系统启动类加载器
}
if (url == null) {//系统启动类加载器没有加载到,递归回退到第一次调用然后是扩展类加载器
url = findResource(name);
}
return url;//最后如果都没有加载到,双亲委派加载失败,则加载应用本身自己的加载器
}
getResource()方法中name = resolveName(name);
private String resolveName(String name) {
if (name == null) {
return name;
}
if (!name.startsWith("/")) { -->//对于不以/开头的文件,
Class> c = this; //获取当前加载类的完整的类路径,例如:/com/ciphergateway/utils/
while (c.isArray()) {
c = c.getComponentType();
}
String baseName = c.getName();
int index = baseName.lastIndexOf('.');//找到文件的包名称
if (index != -1) {
name = baseName.substring(0, index).replace('.', '/')
+"/"+name; //将包名称中的.替换为/ 并在最后加上/ 文件名
}
} else {
name = name.substring(1); //对于/开头的文件名,会只保留文件名称部分。
}
return name;
}
具体说明:
Class.getResource和ClassLoader.getResource 最终调用的是ClassLoader 类的getResource方法。只不过Class.getResource是先调用Class 的 getResource 方法,在这个getResource 方法中,再去调用ClassLoader 类的getResource方法。
二、对于:class.getResource("")
1、PropertiesUtil.class.getResource("").getPath()
Class类中的getResource方法返回的是/com/ciphergateway/utils/ (获取当前加载类的完整的类路径)
ClassLoader类中的getResource方法返回的是
/D:/java_project2021/autocasb/target/classes/com/ciphergateway/utils/
这里获取的文件路径其实是:/D:/java_project2021/autocasb/target/classes/com/ciphergateway/utils/
- PropertiesUtil.class.getResource("/").getPath()
Class类中的getResource方法返回的是""
ClassLoader类中的getResource方法返回的是 file:/C:/myroad/utalitityUtils/target/classes/
- PropertiesUtil.class.getClassLoader().getResource("").getPath()
class.getClassLoader().getResource("")返回的是target/class/
这里获取的文件路径其实是:/D:/java_project2021/autocasb/target/classes
三、对于ClassLoader.getResource
PropertiesUtil.class.getClassLoader().getResource("").getPath()
直接调用的就是ClassLoader 类的getResource方法,那么对于getResource(""),通过当前类加载classpath根下资源文件。
所以这里的路径是:/D:/java_project2021/autocasb/target/classes
四、Class.getResource和ClassLoader.getResource的区别
就是在加载资源文件的时候,加载方式的不同,
class.getResource("/") == class.getClassLoader().getResource("")
其实,Class.getResource和ClassLoader.getResource本质上是一样的,都是使用ClassLoader.getResource加载资源的。
Class.getResource真正调用ClassLoader.getResource方法之前,会先获取文件的路径(path不以'/'开头时,默认是从此类所在的包下取资源;path以'/'开头时,则是从项目的ClassPath根下获取资源)。
ClassLoader.getResource方法会通过双亲委派机制,先委派双亲去加载类,如果双亲没有加载到,则再由自己加载。
classLoader加载顺序,详见https://blog.csdn.net/eff666/article/details/52203406
参考:
https://blog.csdn.net/zhangshk_/article/details/82704010



