Class 、ClassLoader 加载资源


Class 的 getResource 方法,通过ClassLoader实现:

注意参数格式,可以是绝对路径(在 类路径 变量指定的目录下或jar中 查找) 也可以是相对路径相对当前类的类文件包名

resolveName(..)方法将输入的资源名转化为 类路径 下的文件名。

通过该方法可知,除了使用Class加载资源文件外,也可以直接通过ClassLoader加载资源文件,把资源文件当成 一个普通的 类文件 就可以了,只是这时候的 package name 需要把 '.' 变成 '/'

/**
     * 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>'&#92;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>'&#92;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方法:

实现的自己的ClassLoader时,可以复写findResource方法在特定的位置查找资源,默认在在 类路径 下查找,就像查找 类文件一样

/**
     * 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:

loadClass 、loadLibrary:

112135_h8mv_255456.png    

findClass、findLibray、findResource:

112456_K1Gf_255456.png

112630_XRiN_255456.png


下面是一个例子:

114813_9xxW_255456.png

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


转载于:https://my.oschina.net/u/255456/blog/370730

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值