码迷,mamicode.com
首页 > 其他好文 > 详细

加载指定包下的所有类

时间:2018-03-03 21:23:07      阅读:843      评论:0      收藏:0      [点我收藏+]

标签:ide   esc   gpo   runtime   run   pre   init   override   body   

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]

 

加载指定包下的所有类

标签:ide   esc   gpo   runtime   run   pre   init   override   body   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!