现在的位置: 首页 > 综合 > 正文

java ClassLoader加载资源

2017年08月09日 ⁄ 综合 ⁄ 共 2134字 ⁄ 字号 评论关闭

加载资源可以用绝对路径和相对路径,但都有局限性。用硬编码的方式不好。 

比较好的方式是绝对+相对方式。即绝对路径就是应用程序安装的路径,相对路径是资源文件相对于程序根目录的路径。 

java.lang.ClassLoader不仅可以加载类到内存中,还可以加载其它的资源。 

1. ClassLoader.getResourceAsStream 

比方说配置文件,很多时候都是放在源代码路径下的,这样就可以直接使用ClassLoader 

package com.john.basis;  
  
public class MyClass {  
  
InputStream inputStream = MyClass.class.getClassLoader().getResourceAsStream("com/john/basis/conf.properties");  
  
}  

这里的conf.properties是放在com.john.basis包下的,编译的时候IDE会帮我们把资源文件拷贝到生成目录。 

ClassLoader的getResourceAsStream的操作分成两个部分:getResource()和openStream()。 
getSystemResourceAsStream亦是如此。 

下面就以getResourceAsStream为例:

public abstract class ClassLoader {  
  
    public InputStream getResourceAsStream(String name) {  
        URL url = getResource(name);  
        try {  
                return url != null ? url.openStream() : null;  
        } catch (IOException e) {  
                return null;  
        }  
    }  
  
    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;  
    }  
      
    // Sub classes need to override this method  
    protected URL findResource(String name) {  
        return null;  
    }  
}  

如果parent存在,则从parent中getResource();否则从启动引导路径中去找。 
如果url还是null,则调用自定义的findResource()去找。 

2. Class.getResourceAsStream 

jdk帮我们简化了上面的代码,如果conf.properties是和MyClass在同一个目录下,那么可以直接调用类的getResourceAsStream方法: 

InputStream inputStream = MyClass.class.getResourceAsStream("conf.properties");  

其实Class类的getResourceAsStream(name)也是调用了ClassLoader.getResourceAsStream(name)方法的: 

 public InputStream getResourceAsStream(String name) {  
    name = resolveName(name);  
    ClassLoader cl = getClassLoader0();  
    if (cl==null) {  
        // A system class.  
        return ClassLoader.getSystemResourceAsStream(name);  
    }  
    return cl.getResourceAsStream(name);  
} 

如果当前的ClassLoader为null,就调用ClassLoader.getSystemResourceAsStream(name)方法。 

这里对name进行了预处理:

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;  
} 

如果name不是以'/'开头: 
  替换包名中的.为/,将处理后的字符串作为前缀加到name上去。在这里就是:"com/john/basis" + "/" + "conf.properties" 

否则,认为该文件存放在代码根目录,去除首字符'/'。


转载自:http://czj4451.iteye.com/blog/1479532

抱歉!评论已关闭.