加载指定包的所有类(代码、注释很详细)

本文详细介绍了如何在Java Spring环境中加载指定包下的所有类,包括两个关键步骤:1) 获取包的路径;2) 扫描该路径下所有以.class为后缀的文件。

加载指定包的所有类

  • 获取包所在路径
  • 获取路径下的所有后缀为class的文件

1. 获取包所在路径

/**
    * 获取指定包下的所有类
    * 1.获取包所在路径
    * 2.获取路径下的所有class文件
    *
    * @param packageName
    * @return Class对象集合
    */
   public static Set<Class<?>> extractPackageClass(String packageName){
       /*
           1. 获取类加载器:获取项目发布实际路径
           2. 通过类加载器取到加载的资源信息
           3. 依据不同资源类型,采用不同的方式获取资源集合:我们这里获取的时class后缀的类文件
        */
       ClassLoader classLoader = getClassLoader();
       URL url = classLoader.getResource(packageName.replace(".", "/"));
       if (url == null){
           log.warn("unable to retrieve anything from package:"+packageName);
           return null;
       }
       // 过滤文件资源,筛选出文件类型
       Set<Class<?>> classSet = null;
       if(FILE_PROTOCOL.equalsIgnoreCase(url.getProtocol())){
           classSet = new HashSet<Class<?>>();
           File packageDirectory = new File(url.getPath());
           // 获取class后缀的文件,存入到classSet集合
           extractClassFile(classSet,packageDirectory,packageName);
       }
       return classSet;
   }
/**
    * 获取当前线程的ClassLoader
    * @return
    */
   public static ClassLoader getClassLoader(){
       return Thread.currentThread().getContextClassLoader();
   }

2. 获取路径下的所有后缀为class的文件

/**
    * 递归获取目标package里的所有class文件(包括子包)
    *
    * @param classSet      装载目标类的集合
    * @param fileSource    文件或目录
    * @param packageName   包名
    */
   private static void extractClassFile(Set<Class<?>> classSet, File fileSource, String packageName) {
       // 找到资源,终止递归: 非文件夹
       if(!fileSource.isDirectory()){
           return;
       }
       // 如果是文件夹, 获取当前文件下的所有文件和文件夹
       File[] files = fileSource.listFiles(new FileFilter() {
           @Override
           public boolean accept(File file) {
               // 判断是否为文件夹
               if(file.isDirectory()){
                   return true;
               }else {
                   // 获取文件绝对路径
                   String absoluteFilePath = file.getAbsolutePath();
                   if (absoluteFilePath.endsWith(".class")){
                       // 是class类型文件,则直接加载
                       addToClassSet(absoluteFilePath);
                   }
               }
               return false;
           }

           /**
            * 1. 从class文件的绝对路径中获取所有包含package的类名
            * 2. 格式化成com.megetood.dto.MainPageInfoDTO形式
            * 3. 通过反射机制获取对应的Class对象加入到classSet中
            * 
            * @param absoluteFilePath
            */
           private void addToClassSet(String absoluteFilePath) {
               absoluteFilePath = absoluteFilePath.replace(File.separator, ".");
               String className = absoluteFilePath.substring(absoluteFilePath.indexOf(packageName),absoluteFilePath.lastIndexOf("."));
               Class<?> targetClass = loadClass(className);
               classSet.add(targetClass);
           }

       });
       
       // 将获取到的文件夹进行递归操作 
       if (files != null){
           for (File f: files){
               extractClassFile(classSet, f, packageName);
           }
       }
   }
/**
     * 根据类名获取类对象
     *
     * @param className 根包开始的全路径类名
     *                  the fully qualified name of the desired class
     * @return
     */
    public static Class<?> loadClass(String className) {
        try {
            return Class.forName(className);
        } catch (ClassNotFoundException e) {
            log.error("load class error:",e);
            throw new RuntimeException();
        }
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值