包扫描简单示例及其工具化

4 篇文章 0 订阅

包扫描

当我们需要对一些符合条件的类进行特殊处理时,就提出了包扫描这一手段

一些相关代码的简单解释

  • URI 和 URL

 1. URI与URL都是定位资源位置的,就是表示这个资源的位置信息
 2. URL是URI的特例。URL可以打开资源,而URI则不行。
 3. URL和URI对象可以互相转换,使用各自的toURI(),toURL()方法即可
 4. url.getProtocol() 获取该URL的协议名。
  • 包扫描路径获取
Thread.currentThread().getContextClassLoader().getResource("com/mec/study")
  得到的是当前ClassPath的相对路径。
  
  如:file:/E:/college/programme/JavaEE/csdn%e7%b4%a0%e6%9d%90/bin/com/mec/study

  • 获取指定目录下的所有文件
如果想要遍历文件夹中所有文件,包括子文件夹中的文件时,要用到listFiles()方法
  • jar包的处理

 1.   JarURLConnection类通过JAR协议建立了一个访问 jar包URL的连接,可以访问这个jar包或者这个包里的某个文件。
 2.  Enumeration<JarEntry> jarentries = jarfile.entries();  // 得到该jar文件下面的类实体枚举集合

简单示例

我的目录

  1. PackageName目录下只有Class文件
package com.mec.study.packageScan;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

public class DemoForScan {
	public static void main(String[] args) {
		String packageName = "com.mec.study.model";
		packageName = packageName.replace(".","/");
		URL url = Thread.currentThread().getContextClassLoader().getResource(packageName);
		System.out.println(url);
		URI uri;
		try {
			uri = url.toURI();
			File file = new File(uri);
			File[] files = file.listFiles();
			for(File fi : files) {
				System.out.println(fi);
			}
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
	}
}

运行结果

file:/E:/college/programme/JavaEE/csdn%e7%b4%a0%e6%9d%90/bin/com/mec/study/model
E:\college\programme\JavaEE\csdn素材\bin\com\mec\study\model\ActionDefinition.class
E:\college\programme\JavaEE\csdn素材\bin\com\mec\study\model\ActionDemo.class
E:\college\programme\JavaEE\csdn素材\bin\com\mec\study\model\stumodel.class

  1. 将PackageName改为含有子文件的目录
		String packageName = "com.mec.study";
		//  其余代码同上

运行结果

E:\college\programme\JavaEE\csdn素材\bin\com\mec\study\annotation
E:\college\programme\JavaEE\csdn素材\bin\com\mec\study\model
E:\college\programme\JavaEE\csdn素材\bin\com\mec\study\packageScan
E:\college\programme\JavaEE\csdn素材\bin\com\mec\study\test

由以上结果可知当我们需要对同级目录下的文件及其子文件进行扫描获取时,会需要编写多次重复的代码
于是我们想到将该手段做成一个工具供我们以后方便使用

包扫描工具化实现

该工具可以实现对同级目录下的子目录(包括 Jar包的扫描)进行自动扫描获取满足指定条件.Class文件,并对其进行反射机制调用实现其他操作

package com.mec.util;

import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

// 该工具类是一个抽象方法
public abstract class PackageScanner {
	
	// 对指定包下的所有类的处理由使用该工具的用户编写,本工具不提供解决方案,于是将其设定为抽象方法。
	public abstract void dealClass(Class<?> klass);

//  供内部工具使用处理.Class文件
	private void dealClassFile(String rootPackageName,File curfile) {
		String filename = curfile.getName();
		if(filename.endsWith(".class")) {
			filename = filename.replace(".class","");
			try {
				Class<?> klass = Class.forName(rootPackageName + "." + filename);
				dealClass(klass);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
	}
	
	// 处理该rootPackageName目录下的curfile路径下的文件及其子文件
	private void dealDirectory(String rootPackageName,File curfile) {
		File[] files = curfile.listFiles();
		
		for(File file : files) {
			if(file.isDirectory()) {
			//  如果该文件还有子文件则需要再次调用本方法,直到将其扫描完全
				dealDirectory(rootPackageName + "." + file.getName(), file);
			} else if(file.isFile()) {
				dealClassFile(rootPackageName,file);
			}
		}
	}
	
	// 供该工具内部使用的处理Jar包扫描方法
	private void dealJarPackage(URL url) {
		try {
			JarURLConnection connection = (JarURLConnection) url.openConnection();
			JarFile jarfile = connection.getJarFile();
			Enumeration<JarEntry> jarentries = jarfile.entries();
			while(jarentries.hasMoreElements()) {
				JarEntry jarentry = jarentries.nextElement();
				if(jarentry.isDirectory() || !jarentry.getName().endsWith(".class")) {
					continue;
				}
				String jarName = jarentry.getName();
				jarName = jarName.replace(".class","");
				jarName = jarName.replace("/",".");
				
				// 反射机制获取该类,调用dealClass()方法进行具体处理
				Class<?> klass = Class.forName(jarName);
				dealClass(klass);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public void packageScan(String packageName) {
		String packageRoot = packageName;
		packageName = packageName.replace(".","/");
		URL url = Thread.currentThread().getContextClassLoader().getResource(packageName);
		try {
			if(url.getProtocol().equals("file")) {
				URI uri = url.toURI();
				File root = new File(uri);
				dealDirectory(packageRoot, root);
			} else {
				dealJarPackage(url);
			} 
		} catch (URISyntaxException e) {
		e.printStackTrace();
		}
	}
}

工具的使用
(举例: jar包扫描)

package com.mec.study.packageScan;

import com.mec.util.PackageScanner;

public class TestForScanUtil {

	public static void main(String[] args) {
		new PackageScanner() {
			
			@Override
			public void dealClass(Class<?> klass) {
				System.out.println(klass.getName());
			}
		}.packageScan("com.google.gson.internal");
	}
}

运行结果

com.google.gson.annotations.Expose
com.google.gson.annotations.JsonAdapter
com.google.gson.annotations.SerializedName
com.google.gson.annotations.Since
com.google.gson.annotations.Until
com.google.gson.DefaultDateTypeAdapter
com.google.gson.ExclusionStrategy
com.google.gson.FieldAttributes
com.google.gson.FieldNamingPolicy$1
com.google.gson.FieldNamingPolicy$2
com.google.gson.FieldNamingPolicy$3
com.google.gson.FieldNamingPolicy$4
com.google.gson.FieldNamingPolicy$5
com.google.gson.FieldNamingPolicy
com.google.gson.FieldNamingStrategy
com.google.gson.Gson$1
com.google.gson.Gson$2
com.google.gson.Gson$3
com.google.gson.Gson$4
com.google.gson.Gson$5
com.google.gson.Gson$6
com.google.gson.Gson$FutureTypeAdapter
com.google.gson.Gson
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值