2Jul/104
获取指定package路径下的所有class
最近有个需求,通过Annotation来获取class。刚好spring的Annotation注册方式是这样的,于是把spring相关的代码翻了一遍,翻完之后就尝试自己简单实现了下,结果如下。
package us.vifix.a.ape.util;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import sun.net.www.protocol.jar.JarURLConnection;
import us.vifix.a.ape.scheduler.annotation.ExecutorAnnonationFilter;
/**
* author: Anson
* http://a.vifix.us
*/
public final class ClassUtils {
public static List getClassFromPackageWithFilter(String packageName, ClassFilter filter) {
List results = new ArrayList();
// 将包名转换为路径名
String packageDirName = packageName.replace('.', '/');
// 通过路径获取URL
Enumeration resources = null;
try {
resources = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
} catch (IOException e) {
return results;
}
// 遍历获取的URL
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
// 如果是jar包
if ("jar".equals(url.getProtocol())) {
JarFile jarFile = null;
try {
JarURLConnection conn = (JarURLConnection) url.openConnection();
jarFile = conn.getJarFile();
} catch (IOException e) {
continue;
}
// 遍历jar包中的所有entry
for (Enumeration entries = jarFile.entries(); entries.hasMoreElements();) {
JarEntry entry = entries.nextElement();
String entryName = entry.getName();
// 是以指定路径开始&&是class文件&&不是内部类
if (entryName.startsWith(packageDirName)
&& entryName.endsWith(".class")
&& entryName.indexOf("$") == -1) {
// 把路径转变为类名 us/vifix/a/Class.class - us.vifix.a.Class
String className = entryName.replace('/', '.').substring(0, entryName.length() - 6);
// 过滤器
if (filter != null && !filter.filter(className)) continue;
try {
results.add(Class.forName(className));
} catch (ClassNotFoundException e) {
continue;
}
}
}
// 如果是文件系统
} else if ("file".equals(url.getProtocol())) {
String filePath = null;
try {
filePath = URLDecoder.decode(url.getFile(), "UTF-8");
} catch (UnsupportedEncodingException e) {
continue;
}
// 获取根目录并迭代获取所有class
File rootDirectory = new File(filePath);
getClassFromDirectory(packageName, rootDirectory, filter, results);
}
}
return results;
}
private static void getClassFromDirectory(String packageName, File directory, ClassFilter filter, List results) {
// 如果不存在或者不是目录就直接返回
if (!directory.exists() || !directory.isDirectory()) return;
// 获取目录下文件列表 过滤规则为是目录或者是class文件并且不是内部类
File[] files = directory.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return (pathname.isDirectory() || (pathname.getName().endsWith(".class") && pathname.getName().indexOf("$") == -1));
}
});
// 遍历
for (File file : files) {
// 如果是目录 迭代
if (file.isDirectory()) {
getClassFromDirectory(packageName + "." + file.getName(), file, filter, results);
} else {
// 去掉末尾的.class 组装成className
String className = packageName + "." + file.getName().substring(0, file.getName().length() - 6);
// 过滤器
if (filter != null && !filter.filter(className)) continue;
try {
results.add(Class.forName(className));
} catch (ClassNotFoundException e) {
continue;
}
}
}
}
public static void main(String[] args) {
List result = getClassFromPackageWithFilter("javax.crypto", null);
System.out.println("=== result1 ===");
for (Class clazz : result) {
System.out.println(clazz);
}
result = getClassFromPackageWithFilter("us.vifix.a.ape", new ExecutorAnnonationFilter());
System.out.println("=== result2 ===");
for (Class clazz : result) {
System.out.println(clazz);
}
}
}
July 2nd, 2010 - 00:37
我靠 不会自动换行啊 羊子控快去调教
July 2nd, 2010 - 00:46
或者找个自适应宽度的皮 哥的1080p显示器就优势了
July 2nd, 2010 - 09:38
我想不通了,Chronium 6.0.419.0 (48453)在reader里面看代码是正常的,博客里面就不是。囧。
July 2nd, 2010 - 14:29
这个应该是和CSS有关,所以正常