1. 程式人生 > >Java中的包掃描(工具)

Java中的包掃描(工具)

在現在好多應用場景中,我們需要得到某個包名下面所有的類, 包括我們自己在src裡寫的java類和一些第三方提供的jar包裡的類,那麼怎麼來實現呢?

今天帶大家來完成這件事

先分享程式碼

  1 package com.mec.packscanner.core;
  2 
  3 import java.io.File;
  4 import java.io.FileFilter;
  5 import java.io.IOException;
  6 import java.net.JarURLConnection;
  7 import java.net.URISyntaxException;
8 import java.net.URL; 9 import java.util.Enumeration; 10 import java.util.jar.JarEntry; 11 import java.util.jar.JarFile; 12 13 public abstract class PackageScanner { 14 public PackageScanner() {} 15 16 public abstract void dealClass(Class<?> klass); 17 18 //掃描一般的包。
19 private void scanPackage(String packageName,File currentfile) { 20 File[] filelist = currentfile.listFiles(new FileFilter() { 21 //FileFilter是檔案過濾器,原始碼只寫了一個accapt的抽象方法。 22 @Override 23 public boolean accept(File pathName) { 24 if
(pathName.isDirectory()) { //判斷是否是目錄 25 return true; 26 } 27 return pathName.getName().endsWith(".class"); 28 } 29 }); 30 31 for(File file:filelist) { 32 if(file.isDirectory()) { 33 scanPackage(packageName + "." + file.getName(),file); 34 }else { 35 String fileName = file.getName().replace(".class", ""); 36 String className = packageName + "." + fileName; 37 try { 38 Class<?> klass = Class.forName(className);//取出所有的類 39 if(klass.isAnnotation() //不掃描註解類、列舉類、介面和八大基本型別。 40 ||klass.isEnum() 41 ||klass.isInterface() 42 ||klass.isPrimitive()) { 43 continue; 44 } 45 dealClass(klass); 46 } catch (ClassNotFoundException e) { 47 e.printStackTrace(); 48 } 49 } 50 } 51 } 52 53 //掃描jar包方法。 54 private void scanPackage(URL url) throws IOException { 55 JarURLConnection urlConnection = (JarURLConnection) url.openConnection(); 56 JarFile jarfile = urlConnection.getJarFile(); 57 Enumeration<JarEntry> jarEntries = jarfile.entries(); 58 while(jarEntries.hasMoreElements()) { 59 JarEntry jarEntry = jarEntries.nextElement(); 60 String jarName = jarEntry.getName(); 61 if(!jarName.endsWith(".class")) { 62 continue; 63 } 64 String className = jarName.replace(".class", "").replaceAll("/", "."); 65 66 try { 67 Class<?> klass = Class.forName(className); 68 if (klass.isAnnotation() 69 || klass.isInterface() 70 || klass.isEnum() 71 || klass.isPrimitive()) { 72 continue; 73 } 74 dealClass(klass); 75 } catch (ClassNotFoundException e) { 76 e.printStackTrace(); 77 } 78 } 79 } 80 81 //用類名掃描 82 public void packageScan(Class<?> klass) { 83 packageScan(klass.getPackage().getName()); 84 } 85 86 //用包名進行掃描 87 public void packageScan(String packageName) { 88 String packOpperPath = packageName.replace(".","/"); 89 90 //執行緒上下文類載入器得到當前的classpath的絕對路徑.(動態載入資源) 91 ClassLoader classloader = Thread.currentThread().getContextClassLoader(); 92 try { 93 //(Thread.currentThread().getContextClassLoader().getResource("")) 94 //(來得到當前的classpath的絕對路徑的URI表示法。) 95 Enumeration<URL> resources = classloader.getResources(packOpperPath); 96 while(resources.hasMoreElements()) { 97 //先獲得本類的所在位置 98 URL url = resources.nextElement(); 99 100 //url.getProtocol()是獲取URL的HTTP協議。 101 if(url.getProtocol().equals("jar")) { 102 //判斷是不是jar包 103 scanPackage(url); 104 }else { 105 //此方法不會自動將連結中的非法字元轉義。 106 //而在File轉化成URI的時候,會將連結中的特殊字元如#或!等字元進行編碼。 107 File file = new File(url.toURI()); 108 if(!file.exists()) { 109 continue; 110 } 111 scanPackage(packageName,file); 112 } 113 } 114 } catch (IOException e) { 115 e.printStackTrace(); 116 } catch (URISyntaxException e) { 117 e.printStackTrace(); 118 } 119 } 120 }

這個是抽象類,對於掃描,我們只提供掃描的工具,而定義抽象方法是往外接,通過使用者的使用來決定用類名還是包名。

對於jar包的掃描,可以進JarURLConnection類和JarFile類的原始碼中可以理解。