Java 包扫描器

Posted stdpain

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 包扫描器相关的知识,希望对你有一定的参考价值。

包扫描器

获取一个包下的所有类,然后使用默认的类加载器加载到内存中

    public static List<Class<?>> scanByPackage(String packageName) throws IOException, URISyntaxException 
        //我们传入的包名都是 "com.stdpain.xx" 这种的需要替换成 "com/stdpain/xx"
        String packagePath = packageName.replace(".", "/");
        //获取当前类加载器
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        List<Class<?>> classes = new ArrayList<>();
        Enumeration<URL> resources = classLoader.getResources(packagePath);
        while (resources.hasMoreElements()) 
            //获取 url
            URL url = resources.nextElement();
            //判断url是不是一个 jar:// 类型的url 不同的url需要有不同的处理方式,我们默认只有文件系统和jar
            if (url.getProtocol().equals("jar")) 
                //handle jar Package
                System.out.println(url);
                List<Class<?>> scanedClasses = packageJarScan(url);
                classes.addAll(scanedClasses);
             else 
                File file = new File(url.toURI());
                if (!file.exists()) 
                    System.out.println("file not exists = " + file.getAbsolutePath());
                    continue;
                
                System.out.println("scan:" + file.getAbsolutePath());
                //handle file package
                List<Class<?>> scanedClasses = packageScan(file, packageName);
                classes.addAll(scanedClasses);
            
        
        return classes;
    

Jar 处理

    public static List<Class<?>> packageJarScan(URL url) throws IOException 
        //强制类型转换
        JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
        JarFile jarFile = jarURLConnection.getJarFile();
        Enumeration<JarEntry> jarEntries = jarFile.entries();
        List<Class<?>> classes = new ArrayList<>();
        //遍历判断
        while (jarEntries.hasMoreElements()) 
            JarEntry jarEntry = jarEntries.nextElement();
            String jarName = jarEntry.getName();
            if (jarEntry.isDirectory() || !jarName.endsWith(".class")) 
                continue;
            
            String className = jarName.replace(".class", "").replace("/", ".");
            try 
                System.out.println(className);
                Class<?> clazz = Class.forName(className);
                classes.add(clazz);
                System.out.println(className + "->load:success");
             catch (ClassNotFoundException e) 
//                e.printStackTrace();
                System.out.println("e.getMessage() = " + e.getMessage());
            
        
        return classes;
    

文件系统直接递归处理目录就可以

    public static List<Class<?>> packageScan(File curFile, String packageName) 
        ArrayList<Class<?>> classes = new ArrayList<>();
        if (!curFile.isDirectory()) 
            return classes;
        
        File[] files = curFile.listFiles();
        for (File file : files) 
            if (file.isFile() && file.getName().endsWith(".class")) 
                String fileName = file.getName().replace(".class", "");
                String className = packageName + "." + fileName;
                try 
                    Class<?> clazz = Class.forName(className);
                    classes.add(clazz);
                 catch (ClassNotFoundException e) 
                    e.printStackTrace();
                
             else if (file.isDirectory()) 
                //如果是个目录那么就递归处理目录
                classes.addAll(packageScan(file, packageName + "." + file.getName()));
            
        
        return classes;
    

包扫描器有什么用

Spring 中通过注解配置 就是通过包扫描器下每个class是否包含某些注解

以上是关于Java 包扫描器的主要内容,如果未能解决你的问题,请参考以下文章

java 用于反射的Java方法(包扫描)

java扫描某个包下的所有java类并加载

MyBatis 配置多路径XML,多路径接口包扫描

Java扫描classpath指定包路径下所有class

Java笔记-Java端口扫描功能(含TCP包分析以及原理)

springboot配置mapper扫描采坑