包扫描----java

我要写一个包扫描工具,该工具实现从指定目录往下遍历,最终找到以.class文件结尾的类,将该类的元类对象以抽象方法参数的形式传给用户。

步骤: 1.  根据指定目录找出绝对路径,根据Protocol(协议)将目录分为jar目录和普通目录;

    2.  分别处理jar目录和普通目录。

    3.  处理至找到了以.class文件结尾的类,将这个类的元类对象以抽象方法参数的形式传给用户。

直接贴代码:

package com.mec.util;

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

public abstract class PackageScanner {
    public PackageScanner() {
    }
    
    public void scannerPackage(String packageName) {          
        String packagePath = packageName.replace('.', '/'); 
        //Eclipse下父目录与子目录以.相隔
        //真正的路径中是以‘/’或‘\’相隔,此路径以‘\’相隔
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
       try {
            Enumeration<URL> resources = classLoader.getResources(packagePath); 
            //得到绝对路径
              while (resources.hasMoreElements()) {
                  URL url = resources.nextElement();
                  if (url.getProtocol().equals("jar")) {  
                    //通过Protocol(协议)可以区分开jar文件和普通文件
                    scannerJar(url); 
                    // 将处理jar文件的代码单独写成一个内部方法,避免代码量过大
                } else { 
                    File root = new File(url.toURI());
                    //将url转化成uri,以此创建File对象,后面解析就变成了对File的处理
                    scannerDirectory(root, packageName);
                    // 同理将处理普通文件的代码单独也写成一个内部方法
                }
            }
        } catch ( Exception e) {
            e.printStackTrace();
        }
    }

    private void scannerDirectory(File currentFile, String packageName) {
        if (!currentFile.isDirectory()) {
            return;
        }
        File[] files = currentFile.listFiles();
        // 得到File对象类型的【完整路径】的数组
        for (File file : files) {
            if (file.isFile() && file.getName().endsWith(".class")) {
                String fileName = file.getName().replace(".class", ""); 
                //去除掉后缀 .class
                String className = packageName + "." + fileName;
                // 得到带包名的类,为取得元类对象做准备
                try {
                    Class<?> klass = Class.forName(className);
                    dealClass(klass);
                    //将得到的元类对象通过抽象方法参数传递给用户,以便用户后续操作。
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            } else if (file.isDirectory()) {
                scannerDirectory(file, packageName + "." + file.getName());
                // 此处采用递归,只要是目录就继续往下一层遍历,直到file.isFile()为true,且以.class结尾
            }
        }
    }

    private void scannerJar(URL url) {
        try {
            JarURLConnection urlConnection = (JarURLConnection) url.openConnection();
            JarFile jarFile = urlConnection.getJarFile();
             // 取得jar文件的引用
            Enumeration<JarEntry> jarEntries = jarFile.entries();
            //JarFile 的 entries 方法返回一个所有条目的 Enumeration 对象
            while (jarEntries.hasMoreElements()) {
                JarEntry jarEntry = jarEntries.nextElement();
                 //开始遍历,每个个体都是一个 JarEntry, 存在getName()方法
                String name = jarEntry.getName();
                if (jarEntry.isDirectory() || !name.endsWith(".class")) {
                    continue;
                }
                name = name.replace(".class", "");   //去除掉后缀 .class
                String className = name.replace('/', '.');
                Class<?> klass = Class.forName(className);
                dealClass(klass);
                //将得到的元类对象通过抽象方法参数传递给用户,以便用户后续操作。
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
    
    public abstract void dealClass(Class<?> klass);
}

 

 经测试,上述代码可以完成包扫描过程。如果有些地方看不懂,可以上网查一查 。初学者学到这时,不应被  " 巫师的咒语  "吓倒,因为工具复杂,而不愿接受。相反,应站在工具本身发挥的作用角度来思考。积累的多了,见识的广了,才有资格去参悟那些  “  巫师的咒语  ”。

posted on 2019-04-09 21:33  上进小青年!  阅读(231)  评论(0编辑  收藏  举报

导航