专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java通过ClassLoader加载指定的Jar包,并读取Jar包内类上的注解

temp10 2025-02-10 14:24:31 java教程 15 ℃ 0 评论

说明

项目上有个需求,在系统启动时需要动态的加载Jar包,并且扫描jar包中类的注解。

实现

package org.yingqiang.system.annotation.scanner;

import java.io.*;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarInputStream;
import java.util.zip.ZipEntry;

/**
 * 查找jar包下的类是否包含Annotation
 */
public final class JarAnnotationScanner {

    private File jarFile;

    public JarAnnotationScanner(File jarFile) {
        this.jarFile = jarFile;
    }

    /**
     * 扫描
     *
     * @param annotationClass
     */
    public List> scan(Class annotationClass) {
        List> classList = new ArrayList<>();
        try (JarInputStream jarInputStream = new JarInputStream(new FileInputStream(jarFile))) {
            ZipEntry zipEntry;
            while ((zipEntry = jarInputStream.getNextEntry()) != null) {
                String entryName = zipEntry.getName();
                if (entryName.endsWith(".class")) {
                    String className = entryName.replace(".class", "").replaceAll("/", ".");
                    className = className.replaceAll("\\$", ".");
                    byte[] classData = loadClassData(jarInputStream);
                    JarClassLoader jarClassLoader = new JarClassLoader(classData);
                    try {
                        Class clazz = jarClassLoader.findClass(className);
                        Annotation annotation = clazz.getAnnotation(annotationClass);
                        if (annotation != null) {
                            classList.add(clazz);
                        }
                    } catch (Exception e) {
                        // ignore
                    }
                }
                jarInputStream.closeEntry();
            }
        } catch (Exception | NoClassDefFoundError e) {
            System.err.println(e.getMessage());
        }
        return classList;
    }

    /**
     * @param inputStream
     * @return
     * @throws IOException
     */
    private byte[] loadClassData(InputStream inputStream) throws IOException {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                baos.write(buffer, 0, length);
            }
            return baos.toByteArray();
        }
    }

    private class JarClassLoader extends ClassLoader {

        private byte[] classData;

        public JarClassLoader(byte[] classData) {
            this.classData = classData;
        }

        @Override
        protected Class findClass(String name) throws ClassNotFoundException {
            return defineClass(name, classData, 0, classData.length);
        }
    }

    /**
     * @param clazz
     * @return
     */
    public static String getPackageName(Class clazz) {
        if (clazz != null) {
            return clazz.getName().substring(0, clazz.getName().lastIndexOf('.'));
        }
        return "";
    }

}

测试

Java通过ClassLoader加载指定的Jar包,并读取Jar包内类上的注解

package org.yingqiang.system.annotation.scanner;

import java.io.File;
import java.lang.annotation.Annotation;
import java.util.List;

public class JarAnnotationScannerTest {

    public static void main(String[] args) {
        File jarFile = new File("D:\\Temp\\addon\\sms-email.jar");
        JarAnnotationScanner jarAnnotationScanner = new JarAnnotationScanner(jarFile);
        String annotationClassString = "org.springframework.boot.autoconfigure.SpringBootApplication";
        Class annotationClass = null;
        try {
            annotationClass = Class.forName(annotationClassString);
        } catch (ClassNotFoundException e) {
            // e.printStackTrace();
        }
        List> classList = jarAnnotationScanner.scan((Class) annotationClass);
        for (Class clazz : classList) {
            System.out.println(clazz.getName());
            System.out.println(JarAnnotationScanner.getPackageName(clazz));
        }
    }

}

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表