一、前言
通过java.util.jar.JarFile、java.util.jar.JarEntry定义class工具类ClassUtils,实现获取指定包路径为List<Class<?>>集合、通过指定路径或第三方Jar类库的URL引用获取加载class对象,详情代码示例部分。
二、代码示例
import java.io.File;@b@import java.io.FileFilter;@b@import java.io.IOException;@b@import java.net.JarURLConnection;@b@import java.net.URL;@b@import java.util.ArrayList;@b@import java.util.Enumeration;@b@import java.util.List;@b@import java.util.jar.JarEntry;@b@import java.util.jar.JarFile;@b@@b@public class ClassUtils {@b@ @b@ public static List<Class<?>> getClassList(String pkgName , boolean isRecursive, Class<?> parent) {@b@ List<Class<?>> classList = new ArrayList<Class<?>>();@b@ ClassLoader loader = Thread.currentThread().getContextClassLoader();@b@ try {@b@ // 按文件的形式去查找@b@ String strFile = pkgName.replaceAll("\\.", "/");@b@ Enumeration<URL> urls = loader.getResources(strFile);@b@ while (urls.hasMoreElements()) {@b@ URL url = urls.nextElement();@b@ if (url != null) {@b@ String protocol = url.getProtocol();@b@ String pkgPath = url.getPath();@b@ if ("file".equals(protocol)) {@b@ findClassName(classList, pkgName, pkgPath, isRecursive, parent);@b@ } else if ("jar".equals(protocol)) {@b@ findClassName(classList, pkgName, url, isRecursive, parent);@b@ }@b@ }@b@ }@b@ } catch (IOException e) {@b@ e.printStackTrace();@b@ }@b@ @b@ return classList;@b@ }@b@ @b@ public static void findClassName(List<Class<?>> clazzList, String pkgName, String pkgPath, boolean isRecursive, Class<?> parent) {@b@ if(clazzList == null){@b@ return;@b@ }@b@ File[] files = filterClassFiles(pkgPath);// 过滤出.class文件及文件夹@b@ if(files != null){@b@ for (File f : files) {@b@ String fileName = f.getName();@b@ if (f.isFile()) {@b@ // .class 文件的情况@b@ String clazzName = getClassName(pkgName, fileName);@b@ addClassName(clazzList, clazzName, parent);@b@ } else {@b@ // 文件夹的情况@b@ if(isRecursive){@b@ // 需要继续查找该文件夹/包名下的类@b@ String subPkgName = pkgName +"."+ fileName;@b@ String subPkgPath = pkgPath +"/"+ fileName;@b@ findClassName(clazzList, subPkgName, subPkgPath, true, parent);@b@ }@b@ }@b@ }@b@ }@b@ }@b@ @b@ /**@b@ * 第三方Jar类库的引用。<br/>@b@ * @throws IOException @b@ * */@b@ public static void findClassName(List<Class<?>> clazzList, String pkgName, URL url, boolean isRecursive, Class<?> parent) throws IOException {@b@ JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();@b@ JarFile jarFile = jarURLConnection.getJarFile();@b@ System.out.println("jarFile:" + jarFile.getName());@b@ Enumeration<JarEntry> jarEntries = jarFile.entries();@b@ while (jarEntries.hasMoreElements()) {@b@ JarEntry jarEntry = jarEntries.nextElement();@b@ String jarEntryName = jarEntry.getName(); // 类似:sun/security/internal/interfaces/TlsMasterSecret.class@b@ String clazzName = jarEntryName.replace("/", ".");@b@ int endIndex = clazzName.lastIndexOf(".");@b@ String prefix = null;@b@ if (endIndex > 0) {@b@ String prefix_name = clazzName.substring(0, endIndex);@b@ endIndex = prefix_name.lastIndexOf(".");@b@ if(endIndex > 0){@b@ prefix = prefix_name.substring(0, endIndex);@b@ }@b@ }@b@ if (prefix != null && jarEntryName.endsWith(".class")) {@b@// System.out.println("prefix:" + prefix +" pkgName:" + pkgName);@b@ if(prefix.equals(pkgName)){@b@ addClassName(clazzList, clazzName, parent);@b@ } else if(isRecursive && prefix.startsWith(pkgName)){@b@ // 遍历子包名:子类@b@ addClassName(clazzList, clazzName, parent);@b@ }@b@ }@b@ }@b@ }@b@ @b@ private static File[] filterClassFiles(String pkgPath) {@b@ if(pkgPath == null){@b@ return null;@b@ }@b@ // 接收 .class 文件 或 类文件夹@b@ return new File(pkgPath).listFiles(new FileFilter() {@b@ @Override@b@ public boolean accept(File file) {@b@ return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();@b@ }@b@ });@b@ }@b@ @b@ private static String getClassName(String pkgName, String fileName) {@b@ int endIndex = fileName.lastIndexOf(".");@b@ String clazz = null;@b@ if (endIndex >= 0) {@b@ clazz = fileName.substring(0, endIndex);@b@ }@b@ String clazzName = null;@b@ if (clazz != null) {@b@ clazzName = pkgName + "." + clazz;@b@ }@b@ return clazzName;@b@ }@b@ @b@ private static void addClassName(List<Class<?>> clazzList, String clazzName, Class<?> parent) {@b@ if (clazzList != null && clazzName != null) {@b@ Class<?> clazz = null;@b@ try {@b@ clazz = Class.forName(clazzName);@b@ } catch (ClassNotFoundException e) {@b@ }@b@ @b@ if (clazz != null) {@b@ if(parent == null){@b@ clazzList.add(clazz);@b@ } else if (parent.isAssignableFrom(clazz) && parent != clazz){@b@ clazzList.add(clazz);@b@ }@b@ }@b@ }@b@ }@b@}