java中ClassLoader加载资源

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

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

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

[size=large]1. ClassLoader.getResourceAsStream[/size]

比方说配置文件,很多时候都是放在源代码路径下的,这样就可以直接使用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()去找。

[size=large]2. Class.getResourceAsStream[/size]

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"

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值