加载指定包下的所有类

package util;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 类加载
 * 1、从类路径获取所有类
 * 2、获取类加载器,加载类
 * 3、将类放入 set 集合中
 * Created by lay on 27/02/2018.
 */
public class ClassUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(ClassUtil.class);

    /**
     * 获取类加载器(实现最简单)
     *
     * @return
     */
    public static ClassLoader getClassLoader() {
        // 只需要获取当前线程中的ClassLoader即可
        return Thread.currentThread().getContextClassLoader();
    }

    /**
     * 加载类
     *
     * @param className
     * @param isInitialized
     * @return
     */
    public static Class<?> loadClass(String className, boolean isInitialized) {
        Class<?> cls;
        try {
            cls = Class.forName(className, isInitialized, getClassLoader());
        } catch (ClassNotFoundException e) {
            LOGGER.error("load class failure", e);
            throw new RuntimeException(e);
        }
        return cls;
    }

    /**
     * 获取指定包下的所有类
     * 1、根据包名并将其转换为文件路径
     * 2、读取class文件或者jar包
     * 3、获取指定的类名去加载类   * 简单来说:getResouces() 获取文件路径 =》listFiles()获取一级文件 =》递归加载
     * @param packageName 包名
     * @return
     */
    public static Set<Class<?>> getClassSet(String packageName) {
        // Class<?> 表示任意类型
        // 类set集合
        Set<Class<?>> classSet = new HashSet<Class<?>>();

        try {
            // 枚举接口
            Enumeration<URL> urls = getClassLoader().getResources(packageName.replace(".", "/"));

            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                System.out.println(url);
                if (url != null) {
                    // 获取此 URL 的协议名称
                    String protocol = url.getProtocol();
                    // 文件路径
                    if (protocol.equals("file")) {
                        // 空格处理
                        String packagePath = url.getPath().replace("%20", "");
                        addClass(classSet, packagePath, packageName);
                    // jar包
                    } else if (protocol.equals("jar")) {
                        // 初始化Jar文件连接
                        JarURLConnection jarURLConnection = (JarURLConnection)url.openConnection();
                        if (jarURLConnection != null) {
                            // 获取Jar文件
                            JarFile jarFile = jarURLConnection.getJarFile();
                            if (jarFile != null) {
                                // 获取文件条目枚举
                                Enumeration<JarEntry> jarEntries = jarFile.entries();
                                // 遍历条目
                                while (jarEntries.hasMoreElements()) {
                                    JarEntry jarEntry = jarEntries.nextElement();
                                    // 返回条目名称
                                    String jarEntryName = jarEntry.getName();
                                    // 如果是类文件
                                    if (jarEntryName.endsWith(".class")){
                                        // 转换为包路径
                                        String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");
                                        doAddClass(classSet, className);
                                    }
                                }
                            }
                        }
                    }
                }
            }

        } catch (IOException e) {
            LOGGER.error("get class set failure", e);
            throw new RuntimeException(e);
        }

        return classSet;
    }

    /**
     * 添加类
     * @Title: addClass
     * @Description:
     * @param classSet 集合
     * @param packagePath 文件路径
     * @param packageName 包名
     * @return: void
     * @date: Mar 3, 2018
     */
    private static void addClass(Set<Class<?>> classSet, String packagePath, String packageName) {
        // 返回package目录下的所有“抽象路径名”
        File[] files = new File(packagePath).listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                // 是一个class文件,或者 路径
                return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
            }
        });

        for (File file : files) {
            // 获取抽象名
            String fileName = file.getName();
            // 如果是文件
            if (file.isFile()){
                // 类名
                String className = fileName.substring(0, fileName.lastIndexOf("."));
                if (StringUtil.isNotEmpty(packageName)) {
                    // 包名拼接类名
                    className = packageName + "." + className;
                }
                doAddClass(classSet, className);
            // 如果是路径
            }else{
                String subPackagePath = fileName;
                // 拼接到文件路径
                if (StringUtil.isNotEmpty(packagePath)) {
                    subPackagePath = packagePath + "/" + subPackagePath;
                }
                String subPackageName = fileName;
                // 拼接包名
                if (StringUtil.isNotEmpty(subPackageName)){
                    subPackageName = packageName + "." + subPackageName;
                }
                // 执行递归
                addClass(classSet, subPackagePath, subPackageName);
            }
        }
    }

    /**
     * 加载类,置入Set集合中
     * @param classSet
     * @param classsName
     */
    private static void doAddClass(Set<Class<?>> classSet, String classsName){
        Class<?> cls = loadClass(classsName, false);
        classSet.add(cls);
    }
}

测试:

public class Test {
    public static void main(String[] args) {
        Set<Class<?>> classsSet = ClassUtil.getClassSet("cn.lay");     System.out.println(classSet);
    }
}

控制台打印:

[class cn.lay.controller.Test]

原文地址:https://www.cnblogs.com/lay2017/p/8502831.html

时间: 2024-10-13 12:24:05

加载指定包下的所有类的相关文章

加载指定包名下的所有类或根据类的annotation进行过滤的工具类

版权声明:本文为博主原创文章,未经博主允许不得转载.

JVM自定义类加载器加载指定classPath下的所有class及jar

一.JVM中的类加载器类型 从Java虚拟机的角度讲,只有两种不同的类加载器:启动类加载器和其他类加载器. 1.启动类加载器(Boostrap ClassLoader):这个是由c++实现的,主要负责JAVA_HOME/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作. 2.其他类加载器:由java实现,可以在方法区找到其Class对象.这里又细分为几个加载器 a).扩展类加载器(Extension ClassLoader):负责用于加载JAVA_HOM

加载指定包名下的全部类以及指定annotation进行过滤的工具类

package org.konghao.sys.kit; import java.io.File; import java.io.FileFilter; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import o

java动态加载指定的类或者jar包反射调用其方法

序言 有时候,项目中会用到java动态加载指定的类或者jar包反射调用其方法来达到模块的分离,使各个功能之间耦合性大大降低,更加的模块化,代码利用率更高.模式中的代理模式就用到java的这一机制.下边就让我们通过代码来看看如何实现此功能. 代码详细 package loadjarclass; import java.io.File; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoad

ClassLoader加载指定的类需注意六个细节或报ClassNotFundEception异常总结

项目中,加载指定的类反射调用方法一直报类找不到,经过数百次的测试,对这种问题有了一个重新的认识,特总结.记录.分享如下: 1.路径中尽可能用"/"或者File.separator()而非"\\",路径中"\"是windows平台的,linux平台中是"/",java中也是用"/"作为路径的,所以为了跨平台和更规范,建议采用前者 2.在当前的环境中获取绝对路径后,尽可能的replace("\\&qu

java动态加载jar包,并运行其中的类和方法

动态加载jar包,在实际开发中经常会需要用到,尤其涉及平台和业务的关系的时候,业务逻辑部分可以独立出去交给业务方管理,业务方只需要提供jar包,就能在平台上运行. 下面通过一个实例来直观演示: 第一:定义一个抽象类 AbstractAction (稍后换成接口的实例) [java] view plain copy package com.java.loader; public abstract class AbstractAction { public abstract String actio

mahout(或者hadoop)优先使用用户指定的classpath加载jar包

问题:使用mahout0.8时,出现java.lang.NoSuchMethodError: org.apache.lucene.util.PriorityQueue 类似http://www.warski.org/blog/2013/10/using-amazons-elastic-map-reduce-to-compute-recommendations-with-apache-mahout-0-8/ 原因: $HADOOP_HOME/lib下面有个旧版本的lucene-core-3.6.0

javaEE:day2-servlet生命周期、提交解决中文乱码、tomcat加载jar包或类文件的顺序

servlet生命周期 生命周期简介: servlet在服务器第一次被请求的时候new出来,并初始化(即init())再调用service方法.这个实在服务器中new出来,然后用HashMap加的,与客户端无关.客户端之后访问只调用这个servlet的service方法. 具体分为4步: 1 构造方法 :服务器在被客户端第一次请求的时候运行 仅在服务器中运行一次 2 init方法:客户端第一次访问服务器的时候在服务器中进行初始化 仅一次.并且可以通过config参数在 web.xml中通过(ke

解决maven无法加载本地lib/下的jar包问题(程序包XXX不存在)

这次一个项目用到maven编译,我在本地开发的时候jar包都是放在WEB-INF/lib目录下,通过 BuildPath将jar包导入,然后用MyEclipse中的:maven package命令打成war包,这个war包在tomcat下能正常运行,war包下是有lib下的jar包的. 但是我往服务器上传的是项目源码,用SVN上传,然后服务器上用maven插件编译运行,编译时报错:找不到WEB-INF/lib下jar包.显然maven编译时不会自动加载WEB-INF/lib下的jar包. 项目的