您的位置:首页 > 编程语言 > Java开发

java ClassLoader 类加载资源详解

2014-05-28 17:00 253 查看
ClassLoader可以把包(jar包,war包)内的class文件加载到JVM中,第一步就是将class文件以stream的方式读取出来。ClassLoader也将这个加载资源的方法getResourceAsStream暴露了出来。编程时可以使用这个方法来加载包内的任何资源,比如properties文件,图片等。


使用ClassLoader加载资源

当使用ClassLoader加载资源的时候,参数应该是资源文件在包内的路径,不以“/”开头,即使用绝对路径这里的绝对路径是classpath。对于下面的package结构:





如果要加载test2.properties这个文件,getResourceAsStream的参数就是“classloader/getresource/deeper/test2.properties”。

ClassLoader可以加载任何一个在classpath上存在的资源文件,可以不是一个package内,也可以不在一个包内。简单来说,只要把资源文件也当作一个类来看待,把类的全路径名中的“.”换成“/”就可以了。

getResourceAsStream的参数也可以有“..”,用来回到上一层目录。


使用Class加载资源

Class类也有一个getResourceAsStream方法。对于同一个包中的资源文件,使用Class加载资源文件会更简单。

比如上图中,如果GetResourceInCurrentPkg类想加载test.properties,只要使用下面的代码就行了。

GetResourceInCurrentPkg.
class
.getResourceAsStream(
"test.properties"
)


实际上Class类的getResourceAsStream方法内部调用了,ClassLoader类的getResourceAsStream方法。Class类的getResourceAsStream方法

源码如下:

public InputStream getResourceAsStream(String name) {

//调用resolveName方法对资源名进行解析

name = resolveName(name);

//返回当前类的ClassLoader

ClassLoader cl = getClassLoader0();

if (cl==null) {

// A system class.

return ClassLoader.getSystemResourceAsStream(name);

}

//调用当前类的ClassLoader的getResourceAsStream方法

return cl.getResourceAsStream(name);

}

再来看看 Class类resolveName方法的源码

/**

* Add a package name prefix if the name is not absolute Remove leading "/"

* if name is absolute

*/

private String resolveName(String name) {

//当资源名为null时直接返回null

if (name == null) {

return name;

}

/*

***

当资源名不以"/"开始时,对资源名进行解析,上例中的name="test.properties",经解析结果为

name="classloader/getresource/test.properties",即在前面加上了类所在包的路径。

***

*/

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;

}

参照下面的图





下面的示例代码可以成功加载资源

package classloader.getresource;

import java.io.IOException;

import java.util.Properties;

public class GetResourceInCurrentPkg {

/**

* @param args

* @throws IOException

*/

public static void main(String[] args) throws IOException {

// using Class.getResourceAsStream, the default location is the package

// of current class. It is an instance method, so every instance know

// that where is the class, and which package it is, and which class

// loader to

// use. It is a relative path.

Properties props = new Properties();

props.load(GetResourceInCurrentPkg.class

.getResourceAsStream("../getresource/test.properties"));

System.out.println(props.get("test"));

props = new Properties();

props.load(GetResourceInCurrentPkg.class

.getResourceAsStream("test.properties"));

System.out.println(props.get("test"));

props = new Properties();

props.load(GetResourceInCurrentPkg.class

.getResourceAsStream("deeper/test2.properties"));

System.out.println(props.get("test2"));

// if the path start with /, then it means the path is absolute path.

props = new Properties();

props.load(GetResourceInCurrentPkg.class

.getResourceAsStream("/classloader/getresource/deeper/test2.properties"));

System.out.println(props.get("test2"));

// Using class loader, it is always the absolute path.

props = new Properties();

props.load(GetResourceInCurrentPkg.class.getClassLoader()

.getResourceAsStream(

"classloader/getresource/deeper/test2.properties"));

System.out.println(props.get("test2"));

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: