详解Java反射自动扫描某个包内的所有类的简单实现

2022-06-16 14:16:36

学习java反射的时候,了解到可能存在某种场景需要扫描一个包内的所有类的需求,在各个框架中都存在这种需求,配合注解的使用能够实现强大功能,所以尝试实现了一下。

  1. 获取包路径
  2. 获取包内所有文件名
  3. 根据文件名得到反射Class对象

1. 获取包路径(扫描包)

这一部分的功能由于本人原因可能描述的不是很好

这个部分我主要使用的是通过类加载器ClassLoader来进行扫描,之所以使用类加载器的原因是因为源代码java文件一个文件中可能会包含多个类,不能完全的扫描到,而扫描class文件则可以更加全面的获取到包内的所有类

使用扫描class文件的方式还可以获取内部类,注意内部类的class文件名中多一个美元符号$,不过本篇介绍的方法实现中不包含对内部类的获取,这只是一个简单的实现。

首先我们的包名和文件路径是存在差异的,包中表示结构关系的分割符为“ . ”,而系统中表示文件结构关系的分隔符又因操作系统的不同而不同,windows的分隔符为**” \ “** ,所以需要先将完整的包名中的分隔符替换为当前系统的分隔符。

String path= basePackageName.replace(".","\\");

替换后就得到包在输出目录中的文件夹相对路径,再通过ClassLoader的getResources方法获取到绝对路径

//获取编译后的class文件夹路径dirPathEnumeration<URL> enums= loader.getResources(path);String dirPath="";while(enums.hasMoreElements()){URL url= enums.nextElement();if(url!=null){String protool= url.getProtocol();if("file".equals(protool)){
            dirPath= url.getPath();}}}

需要注意的是:这里获取到的绝对路径dirPath中可能会存在**"%e65%e64%e35%e23"**乱码,此时通过这个路径是无法找到正确的文件夹的,需要使用URLDecoder.decode(dirPath,"utf-8");将其转换为UTF-8编码方式消除乱码后能获取到正确的包路径。

2. 获取包内所有文件名

通过上一步骤,我们已经获取到了包的绝对路径,这一步,我们就需要获取包文件夹内的所有文件名。

首先根据包绝对路径实例化一个File对象,通过isDirectory()方法判断是否为文件夹,若不为文件夹则不作任何操作。

当确保是文件夹时,就可以调用File对象的listFiles()方法获取其子文件列表,返回值为一个File类型数组。

遍历得到的子文件数组,通过getName()方法获取文件名,由于通过类名创建反射不需要后缀名,所以我们这里需要将文件夹的后缀名去掉,再添加到结果集列表中。

实现代码如下:

privateList<String>scanForDir(String dirPath){List<String> classNames=newArrayList<>();//根据传入文件夹路径创建File对象File dir=newFile(dirPath);//检查是否为文件夹if(dir.isDirectory()){//遍历文件夹内的文件for(File f: dir.listFiles()){//获取文件名,并删除后缀String fileName= f.getName();
            fileName= fileName.substring(0,fileName.lastIndexOf("."));//添加到结果中
            classNames.add(fileName);}}return classNames;}

3.根据文件名得到反射Class对象

这一步就很简单了,直接遍历所有文件名,通过Class.forName方法得到反射对象

使用Class.forName方法获取反射对象时,需要注意,传入的参数需要的是类的全名,即所在包+类名,所以传参的时候需要将包名给拼接上去

//将获取到的包内文件名转换为反射对象List<Class<?>> classes=newArrayList<>();List<String> classNames=scanForPackageName(packageName);for(String str: classNames){try{
        classes.add(Class.forName(packageName+"."+str));}catch(ClassNotFoundException e){
        e.printStackTrace();}}

以上就是关于自动扫描某个包内的所有类的简单实现,本人水平有限,感觉代码中还存在着不少瑕疵,后续可能会继续完善,如果有存在的问题,还请在评论区留言。

  • 作者:xiyeyee
  • 原文链接:https://blog.csdn.net/INER1/article/details/117492349
    更新时间:2022-06-16 14:16:36