All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.handyplus.lib.core.ClassUtil Maven / Gradle / Ivy

The newest version!
package cn.handyplus.lib.core;

import cn.handyplus.lib.InitApi;
import lombok.SneakyThrows;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 类加载器
 *
 * @author handy
 * @since 1.2.5
 */
public class ClassUtil {

    private final static String CLASS = ".class";
    private final File FILE;
    private final ClassLoader CLASS_LOADER;

    /**
     * 构造类加载器
     */
    public ClassUtil() {
        this.CLASS_LOADER = InitApi.PLUGIN.getClass().getClassLoader();
        try {
            FILE = new File(URLDecoder.decode(InitApi.PLUGIN.getClass().getProtectionDomain().getCodeSource().getLocation().getPath(), StandardCharsets.UTF_8.toString()));
        } catch (UnsupportedEncodingException ignored) {
            throw new NullPointerException("加载异常...");
        }
    }

    /**
     * 扫描注解下的包
     *
     * @param packageName 包名
     * @param annotation  注解
     * @return 类集合
     */
    @SneakyThrows
    public List> getClassByAnnotation(String packageName, Class annotation) {
        List> classList = new ArrayList<>();
        URL jar = FILE.toURI().toURL();
        try (URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{jar}, CLASS_LOADER)) {
            JarInputStream jarInputStream = new JarInputStream(jar.openStream());
            while (true) {
                JarEntry nextJarEntry = jarInputStream.getNextJarEntry();
                if (nextJarEntry == null) {
                    break;
                }
                String name = getName(nextJarEntry);
                if (name == null) {
                    continue;
                }
                if (name.startsWith(packageName)) {
                    String cname = name.substring(0, name.lastIndexOf(CLASS));
                    Class loadClass = urlClassLoader.loadClass(cname);
                    // 判断是否有对应注解
                    if (loadClass.isAnnotationPresent(annotation)) {
                        classList.add(loadClass);
                    }
                }
            }
        }
        return classList;
    }

    /**
     * 扫描注解下的方法
     *
     * @param packageName 包名
     * @param annotation  注解
     * @return 类集合
     */
    @SneakyThrows
    public Map, List> getMethodByAnnotation(String packageName, Class annotation) {
        Map, List> map = MapUtil.of();
        URL jar = FILE.toURI().toURL();
        try (URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{jar}, CLASS_LOADER)) {
            JarInputStream jarInputStream = new JarInputStream(jar.openStream());
            while (true) {
                JarEntry nextJarEntry = jarInputStream.getNextJarEntry();
                if (nextJarEntry == null) {
                    break;
                }
                String name = getName(nextJarEntry);
                if (name == null) {
                    continue;
                }
                if (name.startsWith(packageName)) {
                    List methods = new ArrayList<>();
                    String cname = name.substring(0, name.lastIndexOf(CLASS));
                    Class loadClass = urlClassLoader.loadClass(cname);
                    Method[] declaredMethods = loadClass.getDeclaredMethods();
                    List subCommandMethods = Stream.of(declaredMethods).filter(method -> method.isAnnotationPresent(annotation)).collect(Collectors.toList());
                    if (CollUtil.isNotEmpty(subCommandMethods)) {
                        methods.addAll(subCommandMethods);
                    }
                    map.put(loadClass, methods);
                }
            }
        }
        return map;
    }

    /**
     * 扫描对应包名下接口或者父类的子类
     *
     * @param packageName 包名
     * @param clazz       父类
     * @param          泛型
     * @return 类集合
     */
    @SneakyThrows
    @SuppressWarnings(value = {"unchecked", "rawtypes"})
    public  List> getClassByIsAssignableFrom(String packageName, Class clazz) {
        List> classList = new ArrayList<>();
        URL jar = FILE.toURI().toURL();
        try (URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{jar}, CLASS_LOADER)) {
            JarInputStream jarInputStream = new JarInputStream(jar.openStream());
            while (true) {
                JarEntry nextJarEntry = jarInputStream.getNextJarEntry();
                if (nextJarEntry == null) {
                    break;
                }
                String name = getName(nextJarEntry);
                if (name == null) {
                    continue;
                }
                if (name.startsWith(packageName)) {
                    String cname = name.substring(0, name.lastIndexOf(CLASS));
                    Class loadClass = urlClassLoader.loadClass(cname);
                    if (clazz.isAssignableFrom(loadClass)) {
                        classList.add(loadClass);
                    }
                }
            }
        }
        return classList;
    }

    /**
     * 获取名称
     *
     * @param jarEntry jar
     * @return 名称
     */
    private String getName(JarEntry jarEntry) {
        String name = jarEntry.getName();
        if (name.isEmpty()) {
            return null;
        }
        if (!name.endsWith(CLASS)) {
            return null;
        }
        return name.replace("/", ".");
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy