1. 程式人生 > >包及jar包掃描

包及jar包掃描

public PackageScanner() {
}

//掃描包
private void scanFile(File currentFile, String packageName) {
	//File[] fileList = file.listFiles();
	//得到該資料夾下的所有 類+子資料夾的名稱
	//此處list應為掃描包下的所有類的nameList,所以不應該有檔名稱
	//所以應該加一個檔案過濾器
	File[] fileList = currentFile.listFiles(new FileFilter() {
		@Override
		public boolean accept(File pathname) {
			if(pathname.isDirectory()) {
				return true;
			}
			return pathname.getName().endsWith(".class");
		}
	});
	
	for(File f : fileList) {
		//如果是資料夾,遞迴處理
		if(f.isDirectory()) {
			scanFile(f, packageName + "." + f.getName());
		} else {
			String className = packageName + "." 
					+ f.getName().replace(".class", "");
			try {
				Class<?> klass = Class.forName(className);//得到類 
				//可以篩選類
				if(klass.isAnnotation()//是註解
						|| klass.isEnum()//是列舉
						|| klass.isInterface()//是介面
						|| klass.isPrimitive()) {//是基本型別
						continue;
						//這些型別我們不需要 所以不處理
				}
				dealClass(klass);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
	}
}

//掃描jar包
private void scanJarPackage(URL url) throws IOException {
	//連線jar檔案的一個入口連線定位
	JarURLConnection urlConnection = (JarURLConnection) url.openConnection();	
	JarFile jarFile = urlConnection.getJarFile();//得到jar檔案
	Enumeration<JarEntry> jarEntries = jarFile.entries();
	//讀取jar檔案下的內容
	while(jarEntries.hasMoreElements()) {
		JarEntry jarEntry = jarEntries.nextElement();
		String jarName = jarEntry.getName();
		if (jarEntry.isDirectory() || !jarName.endsWith(".class")) {
			continue;
		}
		
		String className = jarName.replace(".class", "").replaceAll("/", ".");
		try {
			Class<?> klass = Class.forName(className);
			if (klass.isAnnotation() 
					|| klass.isInterface()
					|| klass.isEnum()
					|| klass.isPrimitive()) {
				continue;
			}
			dealClass(klass);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

public void packageScanner(String packageName) {
	String packageRelativePath = packageName.replace('.', '/');
	
	ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
	//執行緒.得到當前執行緒.得到類載入器(當前執行緒即這個test,但不能直接用test. ,
	//因為java是多執行緒的,可能不會得到這個test)
	try {
		Enumeration<URL> resource 
			= classLoader.getResources(packageRelativePath);
		//一個列舉型別集合
		while(resource.hasMoreElements()) {
			URL url = resource.nextElement();
			if(url.getProtocol().equals("jar")) { 
				scanJarPackage(url);
			} else {
				File file = new File(url.toURI());
				if(!file.exists()) {//file不存在
					continue;
				}
				//得到要掃描的包(即資料夾) 此處為classes
				scanFile(file, packageName);
			}
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
}

public abstract void dealClass(Class<?> klass);

public static void main(String[] args) {
	String packageName = "com.zty.classes";
	//path如果是以 / 開頭,就從classpath中去找
	//(classpath是bin目錄或是target的classes目錄)
	//如果不以/開頭,就以當前類的位置開始找
			
	 new PackageScanner(){
		@Override
		public void dealClass(Class<?> klass) {
			System.out.println(klass.getName());
		}
	}.packageScanner(packageName);
}

掃描的包為:
在這裡插入圖片描述

執行結果:
在這裡插入圖片描述

剔除了列舉、介面、註解及基本型別之後的結果。