主要用到的东西:
1、资源获取:
ClassLoader loader = getClass().getClassLoader();
loader.getResources(name);
例如:
loader.getResources("com/test");
可能会找到多个包含"com/test"的资源路径
file:/D:/****/bin/com/test -- file:这个是协议,file代表文件,jar代表架包
jar:file:/D:/****/lib/***.jar!/com/test -- 符号"!/"后面代表着jar内部的路径
jar:file:/D:/****/lib/***2.jar!/com/test
测试的时候发现,极个别 jar包,可以正常使用 jar包中的类,但是通过 ClassLoader.getResources()方法,获取不到 jar资源,但是把 jar包重新打包就又可以获取到了,这个问题待研究。
相关的东西备忘下:
Class和 ClassLoader类里都获取单个资源的方法 getResource()。Class是从当前路径找,从根目录找需要加 "/",ClassLoader直接从根目录找。
Class里面没有获取全部资源的 getResources() 方法。
Class里面有一个比较实用的 getResourceAsStream(),直接可以获取流。
2、Jar包处理:
/* url可以指向jar包中的某个资源 */
JarURLConnection conn = (JarURLConnection) url.openConnection();
/* 获取jar包对象 */
JarFile jar = conn.getJarFile();
/* 获取jar包中的所有资源 */
Enumeration<JarEntry> entrys = jar.entries();
3、文件夹处理:递归遍历文件夹
4、获取 Class对象
ClassLoader loader = getClass().getClassLoader();
loader.loadClass(className);
相关的东西备忘下:
ClassLoader.loadClass()和 Class.forName()是有区别的。
JVM的类加载分三部:loading(加载文件)、linking(加载到JVM)、initializing(类初始化)。
loadClass()只是到 loading步骤,而 forName()可以到 initializing(默认) 或者 linking(参数控制)步骤。
包扫描全部代码:
import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* 类扫描器
*/
public class Scanner {
/** 类加载器 */
private static ClassLoader loader = Scanner.class.getClassLoader();
/**
* 扫描类
*
* @param pack 包名
* @return 类
*/
public static List<Class<?>> scan(String pack) {
pack = pack.replace('.', '/');
Enumeration<URL> urls;
try {
/* 获取资源列表 */
urls = loader.getResources(pack);
} catch (IOException e) {
throw new RuntimeException(e);
}
List<Class<?>> classList = new LinkedList<Class<?>>();
/* 遍历 */
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
String protocol = url.getProtocol();
if ("jar".equals(protocol)) {
/* 如果是jar包内的资源 */
classList.addAll(scanFromJar(url, pack));
} else if ("file".equals(protocol)) {
/* 如果是文件资源 */
classList.addAll(scanFromDir(url, pack));
}
}
return classList;
}
/**
* 获取Jar包类资源
*
* @param url 资源URL
* @param pack 包名
* @return 类
*/
private static List<Class<?>> scanFromJar(URL url, String pack) {
JarFile jar;
try {
/* 获取Jar包文件对象 */
JarURLConnection conn = (JarURLConnection) url.openConnection();
jar = conn.getJarFile();
} catch (IOException e) {
return new LinkedList<Class<?>>();
}
return scanFromJar(jar, pack);
}
/**
* 获取Jar包类资源
*
* @param jar JarFile对象
* @param pack 包名
* @return 类
*/
public static List<Class<?>> scanFromJar(JarFile jar, String pack) {
List<Class<?>> classList = new LinkedList<Class<?>>();
/* 这里取到的是Jar包里所有的文件,需要过滤 */
Enumeration<JarEntry> entrys = jar.entries();
/* 遍历 */
while (entrys.hasMoreElements()) {
String name = entrys.nextElement().getName();
if (name.startsWith(pack) && name.endsWith(".class")) {
String className = name.substring(0, name.length() - 6);
className = className.replace('/', '.');
try {
/* 加载类对象 */
Class<?> c = loader.loadClass(className);
classList.add(c);
} catch (ClassNotFoundException e) {
}
}
}
return classList;
}
/**
* 获取文件夹类资源
*
* @param url 资源URL
* @param pack 包名
* @return 类
*/
private static List<Class<?>> scanFromDir(URL url, String pack) {
File dir;
try {
/* 转行为file对象 */
dir = new File(url.toURI());
} catch (URISyntaxException e) {
return new LinkedList<Class<?>>();
}
return scanFromDir(dir, pack);
}
/**
* 获取文件夹类资源
*
* @param dir 文件夹对象
* @param pack 包名
* @return 类
*/
public static List<Class<?>> scanFromDir(File dir, String pack) {
List<Class<?>> classList = new LinkedList<Class<?>>();
File[] files = dir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
/* 递归 */
classList.addAll(scanFromDir(file, pack + '/' + file.getName()));
} else if (file.getName().endsWith(".class")) {
String fileName = file.getName();
String className = pack + '/' + fileName.substring(0, fileName.length() - 6);
className = className.replace('/', '.');
try {
/* 加载类对象 */
Class<?> c = loader.loadClass(className);
classList.add(c);
} catch (ClassNotFoundException e) {
}
}
}
return classList;
}
}
/* 调用方式 */
List<Class<?>> classList = Scanner.scan("com.test");