java 扫描指定包(包括jar包)

/*未经本人同意,禁止转载。

做工程时,有时候需要扫描指定包,或者指定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;
	}

以上为代码展示下用法

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值