前言:

       在写代码的时候,经常会遇到一些配置包路径的代码,然后框架根据提供的包路径进行扫描,比如Spring。所以这里自己去实现一下扫描包路径下类的代码。

       在看资料的过程中,总结出了两个不同的扫描方式,第一种是在扫描src下的包,这时候使用文件系统就可以获取到包下面的类文件;第二种是扫描jar包中的包路径,这时候需要使用JarURLConnection类了,这个可以将Jar包中目标包路径下的文件生成一个个JarEntity,遍历生成的JarEntitys就可以获取目标类文件。

代码实现:

public class Utils {
    //从包路径下扫描
   
public static Set<Class> getClasses(String packagePath) {
        Set<Class> res = new HashSet<>();
        String path = packagePath.replace(".", "/");
        URL url = Thread.currentThread().getContextClassLoader().getResource(path);
        if (url == null) {
            System.out.println(packagePath + " is not exit");
            return res;
        }
        String protocol = url.getProtocol();
        if ("jar".equalsIgnoreCase(protocol)) {
            try {
                res.addAll(getJarClasses(url, packagePath));
            } catch (IOException e) {
                e.printStackTrace();
                return res;
            }
        } else if ("file".equalsIgnoreCase(protocol)) {
            res.addAll(getFileClasses(url, packagePath));
        }
        return res;
    }
    //获取file路径下的class文件
   
private static Set<Class> getFileClasses(URL url, String packagePath) {
        Set<Class> res = new HashSet<>();
        String filePath = url.getFile();
        File dir = new File(filePath);
        String[] list = dir.list();
        if (list == null) return res;
        for (String classPath : list) {
            if (classPath.endsWith(".class")) {
                classPath = classPath.replace(".class", "");
                try {
                    Class<?> aClass = Class.forName(packagePath + "." + classPath);
                    res.add(aClass);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            } else {
                res.addAll(getClasses(packagePath + "." + classPath));
            }
        }
        return res;
    }
    //使用JarURLConnection类获取路径下的所有类
   
private static Set<Class> getJarClasses(URL url, String packagePath) throws IOException {
        Set<Class> res = new HashSet<>();
        JarURLConnection conn = (JarURLConnection) url.openConnection();
        if (conn != null) {
            JarFile jarFile = conn.getJarFile();
            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry jarEntry = entries.nextElement();
                String name = jarEntry.getName();
                if (name.contains(".class") && name.replaceAll("/", ".").startsWith(packagePath)) {
                    String className = name.substring(0, name.lastIndexOf(".")).replace("/", ".");
                    try {
                        Class clazz = Class.forName(className);
                        res.add(clazz);
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return res;
    }


    public static void main(String[] args) {
        Set<Class> classes = Utils.getClasses("com.ioc");
        classes.addAll(Utils.getClasses("net.sf"));
        for (Class clazz : classes) {
            System.out.println(clazz.getName());
        }
    }
}

这里扫描的src结构是

 

扫描的Jar文件是 cglib.jar

posted on 2018-01-09 23:58  Stark_Tan  阅读(643)  评论(0编辑  收藏  举报