通过class的getResource方法,查找与给定类相关的资源。
1、class中getResource在JDK中的定义
Finds a resource with a given name. The rules for searching resources associated with a given class are implemented by the definingclass loader of the class. This method delegates to this object's class loader. If this object was loaded by the bootstrap class loader, the method delegates to Before delegation, an absolute resource name is constructed from the given resource name using this algorithm:
| getResourcepublic URL getResource(String name)
|
getResource方法的实现如下
//getResource
public java.net.URL getResource(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResource(name);
}
return cl.getResource(name);
}
//resolveName
private String resolveName(String name) {
if (name == null) {
return name;
}
if (!name.startsWith("/")) {
Class c = this;
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;
}
2、classloader中的getResource在JDK中的定义
Finds the resource with the given name. A resource is some data (images, audio, text, etc) that can be accessed by class code in a way that is independent of the location of the code. The name of a resource is a '/'-separated path name that identifies the resource. This method will first search the parent class loader for the resource; if the parent isnull the path of the class loader built-in to the virtual machine is searched. That failing, this method will invoke
| getResourcepublic URL getResource(String name)
|
getResource方法的实现如下
//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;
}
/**
* Find resources from the VM's built-in classloader.
*/
private static URL getBootstrapResource(String name) {
try {
// If this is a known JRE resource, ensure that its bundle is
// downloaded. If it isn't known, we just ignore the download
// failure and check to see if we can find the resource anyway
// (which is possible if the boot class path has been modified).
sun.jkernel.DownloadManager.getBootClassPathEntryForResource(name);
} catch (NoClassDefFoundError e) {
// This happens while Java itself is being compiled; DownloadManager
// isn't accessible when this code is first invoked. It isn't an
// issue, as if we can't find DownloadManager, we can safely assume
// that additional code is not available for download.
}
URLClassPath ucp = getBootstrapClassPath();
Resource res = ucp.getResource(name);
return res != null ? res.getURL() : null;
}
/**
* Finds the resource with the given name. Class loader implementations
* should override this method to specify where to find resources. </p>
*
* @param name
* The resource name
*
* @return A <tt>URL</tt> object for reading the resource, or
* <tt>null</tt> if the resource could not be found
*
* @since 1.2
*/
protected URL findResource(String name) {
return null;
}
3、总结
获取资源是,推荐使用class的getResource方法,它实质上是调用的classloader的getResource方法。
class的getResource方法,对name的路径做了一下解析,
所以,自己没有必要调用classloader的getResource方法(因为它的参数name是有规则要求的,但是在API中没有体现。从类路径下搜索,不能以"/"开头)。
例如:
package org.wsr.spring.demo;
public class Demo {
public static void main(String[] args) throws Exception {
String path = new Demo().getClass().getClassLoader().getResource("").getPath();
System.out.println(path);
path = new Demo().getClass().getResource("").getPath();
System.out.println(path);
path = Demo.class.getResource("text.txt").getPath();
System.out.println(path);
}
}
// output
// /D:/WorkSpace/e_my_work/beantest/target/classes/
// /D:/WorkSpace/e_my_work/beantest/target/classes/org/wsr/spring/demo/
// /D:/WorkSpace/e_my_work/beantest/target/classes/org/wsr/spring/demo/text.txt