package util; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.net.JarURLConnection; import java.net.URL; import java.util.Enumeration; import java.util.HashSet; import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 类加载 * 1、从类路径获取所有类 * 2、获取类加载器,加载类 * 3、将类放入 set 集合中 * Created by lay on 27/02/2018. */ public class ClassUtil { private static final Logger LOGGER = LoggerFactory.getLogger(ClassUtil.class); /** * 获取类加载器(实现最简单) * * @return */ public static ClassLoader getClassLoader() { // 只需要获取当前线程中的ClassLoader即可 return Thread.currentThread().getContextClassLoader(); } /** * 加载类 * * @param className * @param isInitialized * @return */ public static Class<?> loadClass(String className, boolean isInitialized) { Class<?> cls; try { cls = Class.forName(className, isInitialized, getClassLoader()); } catch (ClassNotFoundException e) { LOGGER.error("load class failure", e); throw new RuntimeException(e); } return cls; } /** * 获取指定包下的所有类 * 1、根据包名并将其转换为文件路径 * 2、读取class文件或者jar包 * 3、获取指定的类名去加载类 * 简单来说:getResouces() 获取文件路径 =》listFiles()获取一级文件 =》递归加载 * @param packageName 包名 * @return */ public static Set<Class<?>> getClassSet(String packageName) { // Class<?> 表示任意类型 // 类set集合 Set<Class<?>> classSet = new HashSet<Class<?>>(); try { // 枚举接口 Enumeration<URL> urls = getClassLoader().getResources(packageName.replace(".", "/")); while (urls.hasMoreElements()) { URL url = urls.nextElement(); System.out.println(url); if (url != null) { // 获取此 URL 的协议名称 String protocol = url.getProtocol(); // 文件路径 if (protocol.equals("file")) { // 空格处理 String packagePath = url.getPath().replace("%20", ""); addClass(classSet, packagePath, packageName); // jar包 } else if (protocol.equals("jar")) { // 初始化Jar文件连接 JarURLConnection jarURLConnection = (JarURLConnection)url.openConnection(); if (jarURLConnection != null) { // 获取Jar文件 JarFile jarFile = jarURLConnection.getJarFile(); if (jarFile != null) { // 获取文件条目枚举 Enumeration<JarEntry> jarEntries = jarFile.entries(); // 遍历条目 while (jarEntries.hasMoreElements()) { JarEntry jarEntry = jarEntries.nextElement(); // 返回条目名称 String jarEntryName = jarEntry.getName(); // 如果是类文件 if (jarEntryName.endsWith(".class")){ // 转换为包路径 String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", "."); doAddClass(classSet, className); } } } } } } } } catch (IOException e) { LOGGER.error("get class set failure", e); throw new RuntimeException(e); } return classSet; } /** * 添加类 * @Title: addClass * @Description: * @param classSet 集合 * @param packagePath 文件路径 * @param packageName 包名 * @return: void * @date: Mar 3, 2018 */ private static void addClass(Set<Class<?>> classSet, String packagePath, String packageName) { // 返回package目录下的所有“抽象路径名” File[] files = new File(packagePath).listFiles(new FileFilter() { @Override public boolean accept(File file) { // 是一个class文件,或者 路径 return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory(); } }); for (File file : files) { // 获取抽象名 String fileName = file.getName(); // 如果是文件 if (file.isFile()){ // 类名 String className = fileName.substring(0, fileName.lastIndexOf(".")); if (StringUtil.isNotEmpty(packageName)) { // 包名拼接类名 className = packageName + "." + className; } doAddClass(classSet, className); // 如果是路径 }else{ String subPackagePath = fileName; // 拼接到文件路径 if (StringUtil.isNotEmpty(packagePath)) { subPackagePath = packagePath + "/" + subPackagePath; } String subPackageName = fileName; // 拼接包名 if (StringUtil.isNotEmpty(subPackageName)){ subPackageName = packageName + "." + subPackageName; } // 执行递归 addClass(classSet, subPackagePath, subPackageName); } } } /** * 加载类,置入Set集合中 * @param classSet * @param classsName */ private static void doAddClass(Set<Class<?>> classSet, String classsName){ Class<?> cls = loadClass(classsName, false); classSet.add(cls); } }
测试:
public class Test { public static void main(String[] args) { Set<Class<?>> classsSet = ClassUtil.getClassSet("cn.lay"); System.out.println(classSet); } }
控制台打印:
[class cn.lay.controller.Test]
原文地址:https://www.cnblogs.com/lay2017/p/8502831.html
时间: 2024-10-13 12:24:05