【小工具】包扫描器 ——PackageScanner

在这里插入图片描述

需求 分析:

凡是主流框架,大多都提供了 许多注解
而这些注解被使用后,是如何被程序察觉到的呢?

只有扫描到指定包内的类之后,才能根据这个类的信息,
来判断是否进行后续的操作

那么,这就需要本篇博文的主题 —— 包扫描器 来解决!


本人来展示下代码:

实现 代码:

package edu.youzg.util;

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

/**
 * 包扫描器<br/>
 * scanPackage() —— 扫描指定的包<br/>
 * dealClass() —— 处理扫描到的 类的Class对象
 * 
 * @author Youzg
 */
public abstract class PackageScanner {

    public PackageScanner() {
    }

    /**
     * 处理类
     * @param klass 扫描到的类的Class对象
     */
    public abstract void dealClass(Class<?> klass);

    /**
     * 通过 所传File类参数 以及 相应的包名称 来 处理包
     * @param cur 当前扫描到的File
     * @param packageName 目标包名称
     */
    private void dealPackage(File cur, String packageName) {
        File[] files = cur.listFiles();
        for (File file : files) {    // 遍历这个问渐渐中的所有包含的子文件/子文件夹
            if (file.isFile()) {    // 如果是文件
                String fileName = file.getName();
                if (!fileName.endsWith(".class")) {    // 如果是.class文件
                    continue;
                }
                fileName = fileName.replace(".class", "");
                String className = packageName + "." + fileName;
                try {
                    Class<?> klass = Class.forName(className);
                    dealClass(klass);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            } else {    // 如果是文件夹
                dealPackage(file, packageName + "." + file.getName());
            }
        }
    }

    /**
     * 通过URL来处理相应的Jar包
     * @param url 目标URL
     */
    private void dealJar(URL url) {
        try {
            JarURLConnection connection = (JarURLConnection) url.openConnection();
            JarFile jarFile = connection.getJarFile();
            Enumeration<JarEntry> entryList = jarFile.entries();
            while (entryList.hasMoreElements()) {
                JarEntry jarEntry = entryList.nextElement();
                if (jarEntry.isDirectory() || !jarEntry.getName().endsWith(".class")) {    // 如果是文件夹,或者不是.class文件,运行下一轮循环
                    continue;
                }
                String className = jarEntry.getName();    // 组装我们执行反射机制所需的类名
                className = className.replace(".class", "");
                className = className.replace('/', '.');
                try {
                    Class<?> klass = Class.forName(className);
                    dealClass(klass);    // 处理通过反射机制所获得的类
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 通过 所给的包名称,去扫描 这个包中的所有信息
     * 
     * @param packageName 指定的包名
     */
    public void scanPackage(String packageName) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        String pathName = packageName.replace('.', '/');
        try {
            Enumeration<URL> urls = classLoader.getResources(pathName);
            while (urls.hasMoreElements()) {    // 如果包含很多文件(即:不是文件夹就是Jar包)
                URL url = urls.nextElement();
                if (url.getProtocol().equals("jar")) {    // 如果是Jar包
                    dealJar(url);
                } else {    // 如果是文件夹
                    try {
                        File curFile = new File(url.toURI());
                        dealPackage(curFile, packageName);
                    } catch (URISyntaxException e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

相信看了 很多框架源码的同学 会了解到 本类的重要性的!
那么,在本人《Java 高级技术》专栏中,也极大程度上利用了这个小工具,欢迎 有兴趣的同学 前往观看!

posted @ 2020-04-21 23:54  在下右转,有何贵干  阅读(147)  评论(0编辑  收藏  举报