/*未經本人同意,禁止轉載。
做工程時,有時候需要掃描指定包,或者指定jar包,甚至掃描指定包下指定類,本文章詳細講解如何掃描,以及智能掃描,小編講的很詳細了仔細看。
以下講解, 包掃描和jar包掃描,自動識别包掃描還是jar包掃描。
//下文需要一個ClassLoader,
private ClassLoader classLoader;
public PackageParse() {
}
//因為得到java檔案後我們需要把該檔案的類型傳回給使用者,使用者有該類型,
//就可以得到成員,方法,注解,等等 ,是以提供一個抽象方法,給使用者傳回class<?>類型
public abstract void dealClass(Class<?> klass);
//提供項目下的包比如 com.mec.util (或者提供com.mec.util.test.java)
//傳回值為PackageParse也就是本類型,是為了外部友善使用而已,無其他意思。
public PackageParse scanRoot(String packName) {
//建立類加載器,不懂的可以百度學習下,以及classLoader.getResources
this.classLoader = Thread.currentThread().getContextClassLoader();
//packageName存放包名
String packageName = "";
//如果不含類即不是com.mec.util.test.java格式
if(!packName.contains(".java")) {
//将包名字變成路徑
packageName = packName.replace(".", "/");
} else {
//是com.mec.util.test.java格式
//将路徑變為com/mec/util
int lastIndex = packName.lastIndexOf(".");
int secandIndex = packName.substring(0, lastIndex).lastIndexOf(".");
//設定包命為com.mec.util即為去掉.test.java
packName = packName.substring(0, secandIndex);
//将路徑變為com/mec/util
packageName = packName.substring(0, secandIndex).replace(".", "/");
}
try {
//加載packageName的路徑傳回值為Enumeration<URL>類型
Enumeration<URL> url = classLoader.getResources(packageName);
//如果包名正确且不是空包,循環
while(url.hasMoreElements()) {
URL ur = url.nextElement();
//檢視url的類型
String type = ur.getProtocol();
//如果是jar包類型
if(type.equals("jar")) {
//處理jarbao,方法在後面
dealJar(ur);
//如果是file類型
} else if(type.equals("file")) {
//URL轉換為file類型,File構造方法裡有File(URI uri)
File file = new File(ur.toURI());
//如果file是個目錄
if(file.isDirectory()) {
//調用處理目錄檔案
dealFiles(packName, file);
} else {
//處理檔案
String name = file.getName();
//如果是class檔案處理
if(name.contains(".class")) {
//調用處理java類型的檔案也就是**.class,是我們想要的檔案
deaJavaFile(file, packName);
} else {
//不是繼續循環
continue;
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
return this;
}
//處理目錄檔案
private void dealFiles(String packageName, File file) {
//安全期間判斷下檔案是否存在,存在的話進行操作
if(file.exists()) {
//file一定是目錄型檔案是以得到該目錄下所有檔案周遊它們
File[] files = file.listFiles();
for(File childfile : files) {
//如果子檔案是目錄,則遞歸處理,調用本方法遞歸。
if(childfile.isDirectory()) {
//注意遞歸時候包名字要加上".檔案名"後為新的包名
//因為後面反射時需要類名,也就是com.mec.***
dealFiles(packageName + "." + childfile.getName(), childfile);
} else {
//如果該檔案不是目錄。
String name = childfile.getName();
//該檔案是class類型
if(name.contains(".class")) {
處理它
deaJavaFile(childfile, packageName);
} else {
continue;
}
}
}
} else {
return;
}
}
//得到了我們想要的**.class檔案,處理它,我們希望傳回該類型即可。
private void deaJavaFile(File file, String packageName) {
//以下操作得到類型
int index = file.getName().lastIndexOf(".class");
String filename = file.getName().substring(0, index);
Class<?> klass = null;
try {
klass = Class.forName(packageName + "." + filename);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//得到類型後,使用者怎麼使用這個類型是使用者的事情,和工具無關,是以提供一個抽象方法将klass傳過去
dealClass(klass);
}
//處理jar包類型
private void dealJar(URL url) {
//以下六行都是處理jar的固定方法
JarURLConnection jarURLConnection;
try {
jarURLConnection = (JarURLConnection) url.openConnection();
JarFile jarFile = jarURLConnection.getJarFile();
Enumeration<JarEntry> jarEntries = jarFile.entries();
while(jarEntries.hasMoreElements()) {
JarEntry jar = jarEntries.nextElement();
//如果是目錄,或者不是**.class類型不處理
if(jar.isDirectory() || !jar.getName().endsWith(".class")) {
continue;
}
//處理class類型
String jarName = jar.getName();
int dotIndex = jarName.indexOf(".class");
String className = jarName.substring(0, dotIndex).replace("/", ".");
Class<?> klass = Class.forName(className);
//調用抽象方法,給使用者傳回Class<?>類型
dealClass(klass);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//以上為智能掃描,在提供一個普通掃描方法
//需要檔案的絕對路徑,和該項目下的包名字
public PackageParse scanClassPath(String absolute,String root) {
File file = new File(absolute);
if(file.exists()) {
if(file.isFile()) {
if(file.getName().endsWith(".java")){
int index = file.getName().lastIndexOf(".java");
String filename = file.getName().substring(0, index);
Class<?> klass = null;
try {
klass = Class.forName(root + "." + filename);
dealClass(klass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
return this;
}
以上為代碼展示下用法