栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java实现一个扫描包的工具类实例代码

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java实现一个扫描包的工具类实例代码

前言

在很多的实际场景中,我们需要得到某个包名下面所有的类,比如我们在使用SpringMVC的时候,知道SpringMVC可以扫描指定包下的所有类,在平时的开发中,我们也有这样的场景,所以今天写一个扫描包的工具类,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

代码如下:

package com.gujin.utils;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class HQScanPackage
{
 
 boolean recursive = true;
 
 private List packageNames = new ArrayList();
 
 private HQScanPackageFilter filter = null;
 
 private HQScanPackageListener listener = null;

 
 public boolean isRecursive()
 {
  return recursive;
 }

 
 public void setRecursive(boolean recursive)
 {
  this.recursive = recursive;
 }

 
 public HQScanPackageFilter getFilter()
 {
  return filter;
 }

 
 public void setFilter(HQScanPackageFilter filter)
 {
  this.filter = filter;
 }

 
 public HQScanPackageListener getListener()
 {
  return listener;
 }

 
 public void setListener(HQScanPackageListener listener)
 {
  this.listener = listener;
 }

 
 public void addPackage(String packageName)
 {
  if (packageName == null || !packageName.matches("[\w]+(\.[\w]+)*"))
  {
   throw new IllegalArgumentException("非法包名.");
  }
  this.packageNames.add(packageName);
 }

 
 public void clearPackage()
 {
  this.packageNames.clear();
 }

 
 public void scan()
 {
  for (String packageName : packageNames)
  {
   scan(packageName);
  }
 }

 
 private boolean accept(Class clazz)
 {
  if (this.filter != null)
  {
   return this.filter.accept(clazz);
  }
  return true;
 }

 
 private void trrigeronScanClass(Class clazz)
 {
  if (this.listener != null)
  {
   this.listener.onScanClass(clazz);
  }
 }

 
 private void onScanClass(Class clazz)
 {
  if (accept(clazz))
  {
   trrigeronScanClass(clazz);
  }
 }

 
 private void scan(String packageName)
 {
  // 获取包的名字 并进行替换
  String packageDirName = packageName.replace('.', '/');
  // 定义一个枚举的集合 并进行循环来处理这个目录下的things
  Enumeration dirs = null;
  try
  {
   dirs = Thread.currentThread().getContextClassLoader()
    .getResources(packageDirName);
   // 循环迭代下去
   while (dirs.hasMoreElements())
   {
   // 获取下一个元素
   URL url = dirs.nextElement();
   // 得到协议的名称
   String protocol = url.getProtocol();
   // 如果是以文件的形式保存在服务器上
   if ("file".equals(protocol))
   {
    // 获取包的物理路径
    String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
    // 以文件的方式扫描整个包下的文件 并添加到集合中
    findAndAddClassesInPackageByFile(packageName, filePath);
   }
   else if ("jar".equals(protocol))
   {
    // 如果是jar包文件
    // 定义一个JarFile
    JarFile jar = null;
    try
    {
     // 获取jar
     jar = ((JarURLConnection) url.openConnection()).getJarFile();
     // 从此jar包 得到一个枚举类
     Enumeration entries = jar.entries();
     // 同样的进行循环迭代
     while (entries.hasMoreElements())
     {
      // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如meta-INF等文件
      JarEntry entry = entries.nextElement();
      String name = entry.getName();
      // 如果是以/开头的
      if (name.charAt(0) == '/')
      {
      // 获取后面的字符串
      name = name.substring(1);
      }
      // 如果前半部分和定义的包名相同
      if (name.startsWith(packageDirName))
      {
      int idx = name.lastIndexOf('/');
      // 如果以"/"结尾 是一个包
      if (idx != -1)
      {
// 获取包名 把"/"替换成"."
packageName = name.substring(0, idx).replace('/',
  '.');
      }
      // 如果可以迭代下去 并且是一个包
      if ((idx != -1) || recursive)
      {
// 如果是一个.class文件 而且不是目录
if (name.endsWith(".class") && !entry.isDirectory())
{
 // 去掉后面的".class" 获取真正的类名
 String className = name.substring(
  packageName.length() + 1,
  name.length() - 6);
 try
 {
  // 添加到classes
  // 使用Class.forName会触发类静态方法
  Class clazz = Thread.currentThread()
   .getContextClassLoader().loadClass(
     packageName + '.' + className);
  onScanClass(clazz);
 }
 catch (ClassNotFoundException e)
 {
  System.err.println("加载类出错");
 }
}
      }
      }
     }
    }
    catch (IOException e)
    {
     System.err.println("在扫描用户定义视图时从jar包获取文件出错");
     e.printStackTrace();
    }
   }
   }
  }
  catch (IOException e)
  {
   System.err.println("扫描出错");
   e.printStackTrace();
  }
 }

 
 private void findAndAddClassesInPackageByFile(String packageName,
   String packagePath)
 {
  // 获取此包的目录 建立一个File
  File dir = new File(packagePath);
  // 如果不存在或者 也不是目录就直接返回
  if (!dir.exists() || !dir.isDirectory())
  {
   System.err.println("用户定义包名 " + packageName + " 下没有任何文件");
   return;
  }
  // 如果存在 就获取包下的所有文件 包括目录
  File[] dirfiles = dir.listFiles(new FileFilter()
  {
   // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
   public boolean accept(File file)
   {
   return (recursive && file.isDirectory())
     || (file.getName().endsWith(".class"));
   }
  });
  // 循环所有文件
  for (File file : dirfiles)
  {
   // 如果是目录 则继续扫描
   if (file.isDirectory())
   {
   findAndAddClassesInPackageByFile(packageName + "." + file.getName(),
     file.getAbsolutePath());
   }
   else
   {
   // 如果是java类文件 去掉后面的.class 只留下类名
   String className = file.getName().substring(0,
     file.getName().length() - 6);
   try
   {
    Class clazz = Thread.currentThread().getContextClassLoader()
      .loadClass(packageName + '.' + className);
    onScanClass(clazz);
   }
   catch (ClassNotFoundException e)
   {
    System.err.println("添加用户自定义视图类错误 找不到此类的.class文件");
    e.printStackTrace();
   }
   }
  }
 }

 
 public static interface HQScanPackageFilter
 {
  
  public boolean accept(Class clazz);
 }

 
 public static interface HQScanPackageListener
 {
  
  public void onScanClass(Class clazz);
 }

 public static void main(String[] args)
 {
  HQScanPackage scanPackage = new HQScanPackage();
  scanPackage.addPackage(HQScanPackage.class.getPackage().getName());
  scanPackage.setFilter(new HQScanPackageFilter()
  {

   @Override
   public boolean accept(Class clazz)
   {
   return true;
   }
  });
  scanPackage.setListener(new HQScanPackageListener()
  {

   @Override
   public void onScanClass(Class clazz)
   {
   System.out.println(clazz);
   }
  });
  scanPackage.scan();
 }
}

运行可以得到如下结果:

class com.gujin.utils.HQScanPackage$1 
class com.gujin.utils.HQScanPackage$2 
class com.gujin.utils.HQScanPackage$3 
interface com.gujin.utils.HQScanPackage$HQScanPackageFilter 
interface com.gujin.utils.HQScanPackage$HQScanPackageListener 
class com.gujin.utils.HQScanPackage 

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对考高分网的支持。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/143710.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号