Java中的包扫描(工具)

在现在好多应用场景中,我们需要得到某个包名下面所有的类, 包括我们自己在src里写的java类和一些第三方提供的jar包里的类,那么怎么来实现呢?

今天带大家来完成这件事

先分享代码

1.这个类是一个抽象类,对类的处理交给用户,所以就有了dealClass的抽象方法。

  1 package com.mec.packscanner.core;
  2 
  3 import java.io.File;
  4 import java.io.FileFilter;
  5 import java.io.IOException;
  6 import java.net.JarURLConnection;
  7 import java.net.URISyntaxException;
  8 import java.net.URL;
  9 import java.util.Enumeration;
 10 import java.util.jar.JarEntry;
 11 import java.util.jar.JarFile;
 12 
 13 public abstract class PackageScanner {
 14     public PackageScanner() {}
 15     
 16     public abstract void dealClass(Class<?> klass);
 17     
 18     //扫描一般的包。
 19     private void scanPackage(String packageName,File currentfile) {
 20         File[] filelist = currentfile.listFiles(new FileFilter() {
 21             //FileFilter是文件过滤器,源代码只写了一个accapt的抽象方法。
 22             @Override
 23             public boolean accept(File pathName) {
 24                 if(pathName.isDirectory()) {    //判断是否是目录
 25                     return true;
 26                 }
 27                 return pathName.getName().endsWith(".class");
 28             }
 29         });
 30         
 31         for(File file:filelist) {
 32             if(file.isDirectory()) {
 33                 scanPackage(packageName + "." + file.getName(),file);
 34             }else {
 35                 String fileName = file.getName().replace(".class", "");
 36                 String className = packageName + "." + fileName;
 37                 try {
 38                     Class<?> klass = Class.forName(className);//取出所有的类
 39                     if(klass.isAnnotation() //不扫描注解类、枚举类、接口和八大基本类型。
 40                             ||klass.isEnum()
 41                             ||klass.isInterface()
 42                             ||klass.isPrimitive()) {
 43                         continue;
 44                     }
 45                     dealClass(klass);
 46                 } catch (ClassNotFoundException e) {
 47                     e.printStackTrace();
 48                 }
 49             }
 50         }
 51     }
 52     
 53     //扫描jar包方法。
 54     private void scanPackage(URL url) throws IOException {
 55         JarURLConnection urlConnection = (JarURLConnection) url.openConnection();
 56         JarFile jarfile = urlConnection.getJarFile();
 57         Enumeration<JarEntry> jarEntries = jarfile.entries();
 58         while(jarEntries.hasMoreElements()) {
 59             JarEntry jarEntry = jarEntries.nextElement();
 60             String jarName = jarEntry.getName();
 61             if(!jarName.endsWith(".class")) {
 62                 continue;
 63             }
 64             String className = jarName.replace(".class", "").replaceAll("/", ".");
 65             
 66             try {
 67                 Class<?> klass = Class.forName(className);
 68                 if (klass.isAnnotation() 
 69                         || klass.isInterface()
 70                         || klass.isEnum()
 71                         || klass.isPrimitive()) {
 72                     continue;
 73                 }
 74                 dealClass(klass);
 75             } catch (ClassNotFoundException e) {
 76                 e.printStackTrace();
 77             }
 78         }
 79     }
 80     
 81     //用类名扫描
 82     public void packageScan(Class<?> klass) {
 83         packageScan(klass.getPackage().getName());
 84     }
 85     
 86     //用包名进行扫描
 87     public void packageScan(String packageName) {
 88         String packOpperPath = packageName.replace(".","/");
 89         
 90         //线程上下文类加载器得到当前的classpath的绝对路径.(动态加载资源)
 91         ClassLoader classloader = Thread.currentThread().getContextClassLoader();
 92         try {
 93             //(Thread.currentThread().getContextClassLoader().getResource(""))
 94             //(来得到当前的classpath的绝对路径的URI表示法。)
 95             Enumeration<URL> resources = classloader.getResources(packOpperPath);
 96             while(resources.hasMoreElements()) {
 97                 //先获得本类的所在位置                
 98                 URL url = resources.nextElement();
 99                 
100                 //url.getProtocol()是获取URL的HTTP协议。
101                 if(url.getProtocol().equals("jar")) {
102                 //判断是不是jar包
103                     scanPackage(url);
104                 }else {
105                     //此方法不会自动将链接中的非法字符转义。
106                     //而在File转化成URI的时候,会将链接中的特殊字符如#或!等字符进行编码。
107                     File file = new File(url.toURI());
108                     if(!file.exists()) {
109                         continue;
110                     }
111                     scanPackage(packageName,file);
112                 }
113             }
114         } catch (IOException e) {
115             e.printStackTrace();
116         } catch (URISyntaxException e) {
117             e.printStackTrace();
118         }
119     }
120 }

这个是抽象类,对于扫描,我们只提供扫描的工具,而定义抽象方法是往外接,通过使用者的使用来决定用类名还是包名。

对于jar包的扫描,可以进JarURLConnection类和JarFile类的源码中可以理解。

 2.定义测试类,它是扫描jar包的:

 1 package com.mec.packscanner.test;
 2 
 3 import com.mec.packscanner.core.PackageScanner;
 4 
 5 public class Test {
 6 
 7     public static void main(String[] args) {
 8         new PackageScanner() {
 9             
10             @Override
11             public void dealClass(Class<?> klass) {
12                 System.out.println(klass.getName());
13                 
14             }
15         }.packageScan("com.mec.xml_view.core");;
16     }
17 
18 }

结果:

 从结果我们可以看出把jar包中的每一个class都输出了,匿名内部类都被扫描出来了。

我们来看看普通包的结果吧:

 1 package com.mec.packscanner.test;
 2 
 3 import com.mec.packscanner.core.PackageScanner;
 4 
 5 public class Test {
 6 
 7     public static void main(String[] args) {
 8         new PackageScanner() {
 9             
10             @Override
11             public void dealClass(Class<?> klass) {
12                 System.out.println(klass.getName());
13                 
14             }
15         }.packageScan("com.mec.server_client.core");;
16     }
17 
18 }

对普通的包也是,这个例子除了接口,其他的都被扫描出来了。

若有漏洞,请指正!感谢您的阅读。

原文地址:https://www.cnblogs.com/youdiaodaxue16/p/9813087.html