Class 的 getResource 方法,經過ClassLoader實現:java
注意參數格式,能夠是絕對路徑(在 類路徑 變量指定的目錄下或jar中 查找) 也能夠是相對路徑(相對當前類的類文件包名)bootstrap
resolveName(..)方法將輸入的資源名轉化爲 類路徑 下的文件名。ide
經過該方法可知,除了使用Class加載資源文件外,也能夠直接經過ClassLoader加載資源文件,把資源文件當成 一個普通的 類文件 就能夠了,只是這時候的 package name 須要把 '.' 變成 '/'ui
/** * Finds a resource with a given name. The rules for searching resources * associated with a given class are implemented by the defining * {@linkplain ClassLoader class 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 {@link * ClassLoader#getSystemResource}. * * <p> Before delegation, an absolute resource name is constructed from the * given resource name using this algorithm: * * <ul> * * <li> If the {@code name} begins with a {@code '/'} * (<tt>'\u002f'</tt>), then the absolute name of the resource is the * portion of the {@code name} following the {@code '/'}. * * <li> Otherwise, the absolute name is of the following form: * * <blockquote> * {@code modified_package_name/name} * </blockquote> * * <p> Where the {@code modified_package_name} is the package name of this * object with {@code '/'} substituted for {@code '.'} * (<tt>'\u002e'</tt>). * * </ul> * * @param name name of the desired resource * @return A {@link java.net.URL} object or {@code null} if no * resource with this name is found * @since JDK1.1 */ 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); }
ClassLoader 的getResource方法:this
實現的本身的ClassLoader時,能夠複寫findResource方法在特定的位置查找資源,默認在在 類路徑 下查找,就像查找 類文件同樣url
/** * 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. * * <p> The name of a resource is a '<tt>/</tt>'-separated path name that * identifies the resource. * * <p> This method will first search the parent class loader for the * resource; if the parent is <tt>null</tt> the path of the class loader * built-in to the virtual machine is searched. That failing, this method * will invoke {@link #findResource(String)} to find the resource. </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 or the invoker * doesn't have adequate privileges to get the resource. * * @since 1.1 */ 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 a resource of the specified name from the search path used to load * classes. This method locates the resource through the system class * loader (see {@link #getSystemClassLoader()}). </p> * * @param name * The resource name * * @return A {@link java.net.URL <tt>URL</tt>} object for reading the * resource, or <tt>null</tt> if the resource could not be found * * @since 1.1 */ public static URL getSystemResource(String name) { ClassLoader system = getSystemClassLoader(); if (system == null) { return getBootstrapResource(name); } return system.getResource(name); } /** * Returns an enumeration of {@link java.net.URL <tt>URL</tt>} objects * representing all the resources with the given name. Class loader * implementations should override this method to specify where to load * resources from. </p> * * @param name * The resource name * * @return An enumeration of {@link java.net.URL <tt>URL</tt>} objects for * the resources * * @throws IOException * If I/O errors occur * * @since 1.2 */ protected Enumeration<URL> findResources(String name) throws IOException { return java.util.Collections.emptyEnumeration(); }
ClassLoader:spa
loadClass 、loadLibrary:.net
findClass、findLibray、findResource:code
下面是一個例子:orm
package test; import java.net.URL; public class LoadResourceByClassLoader { public static void main(String[] args){ LoadResource lr = new LoadResource(); lr.load(); } } class LoadResource{ public void load(){ ClassLoader cl = this.getClass().getClassLoader(); String name = resolveName("/abs.txt"); URL aurl = cl.getResource(name); System.out.println(aurl != null? "resource url:" + aurl.toString(): "/abs.txt is null"); name = resolveName("abs.txt"); aurl = cl.getResource(name); System.out.println(aurl != null? "resource url:" + aurl.toString(): "abs.txt is null"); name = resolveName("relative.txt"); URL rurl = cl.getResource(name); System.out.println(rurl != null? "resource url:" + rurl.toString(): "relative.txt is null"); name = resolveName("d/relative.txt"); rurl = cl.getResource(name); System.out.println(rurl != null? "resource url:" + rurl.toString(): "relative.txt is null"); } /** * Copied from Class.java * * Add a package name prefix if the name is not absolute Remove leading "/" * if name is absolute */ private String resolveName(String name) { System.out.println( "befor resolving: " + name ); if (name == null) { return name; } if (!name.startsWith("/")) { Class<?> c = this.getClass(); 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); } System.out.println(" after resolving: " +name ); return name; } }
輸出:
befor resolving: /abs.txt
after resolving: abs.txt
resource url:file:/Users/may/Documents/workspace/TESTcore/bin/abs.txt
befor resolving: abs.txt
after resolving: test/abs.txt
abs.txt is null
befor resolving: relative.txt
after resolving: test/relative.txt
resource url:file:/Users/may/Documents/workspace/TESTcore/bin/test/relative.txt
befor resolving: d/relative.txt
after resolving: test/d/relative.txt
resource url:file:/Users/may/Documents/workspace/TESTcore/bin/test/d/relative.txt