前言:
在写代码的时候,经常会遇到一些配置包路径的代码,然后框架根据提供的包路径进行扫描,比如Spring。所以这里自己去实现一下扫描包路径下类的代码。
在看资料的过程中,总结出了两个不同的扫描方式,第一种是在扫描src下的包,这时候使用文件系统就可以获取到包下面的类文件;第二种是扫描jar包中的包路径,这时候需要使用JarURLConnection类了,这个可以将Jar包中目标包路径下的文件生成一个个JarEntity,遍历生成的JarEntitys就可以获取目标类文件。
代码实现:
public class Utils { //从包路径下扫描 public static Set<Class> getClasses(String packagePath) { Set<Class> res = new HashSet<>(); String path = packagePath.replace(".", "/"); URL url = Thread.currentThread().getContextClassLoader().getResource(path); if (url == null) { System.out.println(packagePath + " is not exit"); return res; } String protocol = url.getProtocol(); if ("jar".equalsIgnoreCase(protocol)) { try { res.addAll(getJarClasses(url, packagePath)); } catch (IOException e) { e.printStackTrace(); return res; } } else if ("file".equalsIgnoreCase(protocol)) { res.addAll(getFileClasses(url, packagePath)); } return res; } //获取file路径下的class文件 private static Set<Class> getFileClasses(URL url, String packagePath) { Set<Class> res = new HashSet<>(); String filePath = url.getFile(); File dir = new File(filePath); String[] list = dir.list(); if (list == null) return res; for (String classPath : list) { if (classPath.endsWith(".class")) { classPath = classPath.replace(".class", ""); try { Class<?> aClass = Class.forName(packagePath + "." + classPath); res.add(aClass); } catch (ClassNotFoundException e) { e.printStackTrace(); } } else { res.addAll(getClasses(packagePath + "." + classPath)); } } return res; } //使用JarURLConnection类获取路径下的所有类 private static Set<Class> getJarClasses(URL url, String packagePath) throws IOException { Set<Class> res = new HashSet<>(); JarURLConnection conn = (JarURLConnection) url.openConnection(); if (conn != null) { JarFile jarFile = conn.getJarFile(); Enumeration<JarEntry> entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry jarEntry = entries.nextElement(); String name = jarEntry.getName(); if (name.contains(".class") && name.replaceAll("/", ".").startsWith(packagePath)) { String className = name.substring(0, name.lastIndexOf(".")).replace("/", "."); try { Class clazz = Class.forName(className); res.add(clazz); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } } return res; } public static void main(String[] args) { Set<Class> classes = Utils.getClasses("com.ioc"); classes.addAll(Utils.getClasses("net.sf")); for (Class clazz : classes) { System.out.println(clazz.getName()); } } } |
这里扫描的src结构是
扫描的Jar文件是 cglib.jar