欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java 如何掃描指定包下類(包括jar中的java類)

 更新時間:2021年04月19日 10:05:24   作者:白彬2017  
這篇文章主要介紹了java 如何掃描指定包下類(包括jar中的java類),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

在很多的實際場景中,我們需要得到某個包名下面所有的類,

包括我們自己在src里寫的java類和一些第三方提供的jar包里的類,那么怎么來實現(xiàn)呢?

今天帶大家來完成這件事。

src下面的類如何獲?。?/h2>

首先,比較簡單的是得到我們自己寫的類,我們先來完成這個,

項目的結(jié)構(gòu)圖如下:

我故意創(chuàng)建了這么個比較復(fù)雜的項目結(jié)構(gòu),現(xiàn)在我們就來獲取com.baibin包下所有的類,并且打印他們,代碼如下:

import org.junit.Test;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class Main {
    List<String> classPaths = new ArrayList<String>();
    @Test
    public void searchClass() throws ClassNotFoundException {
        //包名
        String basePack = "com.baibin";
        //先把包名轉(zhuǎn)換為路徑,首先得到項目的classpath
        String classpath = Main.class.getResource("/").getPath();
        //然后把我們的包名basPach轉(zhuǎn)換為路徑名
        basePack = basePack.replace(".", File.separator);
        //然后把classpath和basePack合并
        String searchPath = classpath + basePack;
        doPath(new File(searchPath));
        //這個時候我們已經(jīng)得到了指定包下所有的類的絕對路徑了。我們現(xiàn)在利用這些絕對路徑和java的反射機制得到他們的類對象
        for (String s : classPaths) {
            //把 D:\work\code\20170401\search-class\target\classes\com\baibin\search\a\A.class 這樣的絕對路徑轉(zhuǎn)換為全類名com.baibin.search.a.A
            s = s.replace(classpath.replace("/","\\").replaceFirst("\\\\",""),"").replace("\\",".").replace(".class","");
            Class cls = Class.forName(s);
            System.out.println(cls);
        }
    }
    /**
     * 該方法會得到所有的類,將類的絕對路徑寫入到classPaths中
     * @param file
     */
    private void doPath(File file) {
        if (file.isDirectory()) {//文件夾
            //文件夾我們就遞歸
            File[] files = file.listFiles();
            for (File f1 : files) {
                doPath(f1);
            }
        } else {//標準文件
            //標準文件我們就判斷是否是class文件
            if (file.getName().endsWith(".class")) {
                //如果是class文件我們就放入我們的集合中。
                classPaths.add(file.getPath());
            }
        }
    }
}

效果如下:

總結(jié):這樣的src下面的都比較容易處理,也很容易想到,但是jar包下面的就沒這么簡單了,

但是還是有辦法的。

jar中的類如何獲?。?/h2>

jar下的類我們可以通過JarURLConnection類來或者,代碼如下:

import org.junit.Test;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class JarMain {
    @Test
    public void searchClass() throws IOException, ClassNotFoundException {
        String basePack = "org.junit";
        //通過當前線程得到類加載器從而得到URL的枚舉
        Enumeration<URL> urlEnumeration = Thread.currentThread().getContextClassLoader().getResources(basePack.replace(".", "/"));
        while (urlEnumeration.hasMoreElements()) {
            URL url = urlEnumeration.nextElement();//得到的結(jié)果大概是:jar:file:/C:/Users/ibm/.m2/repository/junit/junit/4.12/junit-4.12.jar!/org/junit
            String protocol = url.getProtocol();//大概是jar
            if ("jar".equalsIgnoreCase(protocol)) {
                //轉(zhuǎn)換為JarURLConnection
                JarURLConnection connection = (JarURLConnection) url.openConnection();
                if (connection != null) {
                    JarFile jarFile = connection.getJarFile();
                    if (jarFile != null) {
                        //得到該jar文件下面的類實體
                        Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
                        while (jarEntryEnumeration.hasMoreElements()) {
                            /*entry的結(jié)果大概是這樣:
                                    org/
                                    org/junit/
                                    org/junit/rules/
                                    org/junit/runners/*/
                            JarEntry entry = jarEntryEnumeration.nextElement();
                            String jarEntryName = entry.getName();
                            //這里我們需要過濾不是class文件和不在basePack包名下的類
                            if (jarEntryName.contains(".class") && jarEntryName.replaceAll("/",".").startsWith(basePack)) {
                                String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replace("/", ".");
                                Class cls = Class.forName(className);
                                System.out.println(cls);
                            }
                        }
                    }
                }
            }
        }
    }
}

通過這兩種方式我們就可以得到指定包名下面所有的類了,這個還是挺有用的,

比如spring中經(jīng)常用來掃描指定包注解的實現(xiàn)等。

補充:獲取指定包名下的所有類

寫了一個工具類,用于獲取指定包名下的所有類,支持遞歸遍歷,支持注解過濾,可從 classpath (class 文件與 jar 包)中獲取。

import java.io.File;
import java.io.FileFilter;
import java.lang.annotation.Annotation;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class ClassUtil {
    // 獲取指定包名下的所有類
    public static List<Class<?>> getClassList(String packageName, boolean isRecursive) {
        List<Class<?>> classList = new ArrayList<Class<?>>();
        try {
            Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packageName.replaceAll("\\.", "/"));
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                if (url != null) {
                    String protocol = url.getProtocol();
                    if (protocol.equals("file")) {
                        String packagePath = url.getPath();
                        addClass(classList, packagePath, packageName, isRecursive);
                    } else if (protocol.equals("jar")) {
                        JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
                        JarFile jarFile = jarURLConnection.getJarFile();
                        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("/", ".");
                                if (isRecursive || className.substring(0, className.lastIndexOf(".")).equals(packageName)) {
                                    classList.add(Class.forName(className));
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return classList;
    }
    // 獲取指定包名下的所有類(可根據(jù)注解進行過濾)
    public static List<Class<?>> getClassListByAnnotation(String packageName, Class<? extends Annotation> annotationClass) {
        List<Class<?>> classList = new ArrayList<Class<?>>();
        try {
            Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packageName.replaceAll("\\.", "/"));
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                if (url != null) {
                    String protocol = url.getProtocol();
                    if (protocol.equals("file")) {
                        String packagePath = url.getPath();
                        addClassByAnnotation(classList, packagePath, packageName, annotationClass);
                    } else if (protocol.equals("jar")) {
                        JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
                        JarFile jarFile = jarURLConnection.getJarFile();
                        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("/", ".");
                                Class<?> cls = Class.forName(className);
                                if (cls.isAnnotationPresent(annotationClass)) {
                                    classList.add(cls);
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return classList;
    }
    private static void addClass(List<Class<?>> classList, String packagePath, String packageName, boolean isRecursive) {
        try {
            File[] files = getClassFiles(packagePath);
            if (files != null) {
                for (File file : files) {
                    String fileName = file.getName();
                    if (file.isFile()) {
                        String className = getClassName(packageName, fileName);
                        classList.add(Class.forName(className));
                    } else {
                        if (isRecursive) {
                            String subPackagePath = getSubPackagePath(packagePath, fileName);
                            String subPackageName = getSubPackageName(packageName, fileName);
                            addClass(classList, subPackagePath, subPackageName, isRecursive);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static File[] getClassFiles(String packagePath) {
        return new File(packagePath).listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
            }
        });
    }
    private static String getClassName(String packageName, String fileName) {
        String className = fileName.substring(0, fileName.lastIndexOf("."));
        if (StringUtil.isNotEmpty(packageName)) {
            className = packageName + "." + className;
        }
        return className;
    }
    private static String getSubPackagePath(String packagePath, String filePath) {
        String subPackagePath = filePath;
        if (StringUtil.isNotEmpty(packagePath)) {
            subPackagePath = packagePath + "/" + subPackagePath;
        }
        return subPackagePath;
    }
    private static String getSubPackageName(String packageName, String filePath) {
        String subPackageName = filePath;
        if (StringUtil.isNotEmpty(packageName)) {
            subPackageName = packageName + "." + subPackageName;
        }
        return subPackageName;
    }
    private static void addClassByAnnotation(List<Class<?>> classList, String packagePath, String packageName, Class<? extends Annotation> annotationClass) {
        try {
            File[] files = getClassFiles(packagePath);
            if (files != null) {
                for (File file : files) {
                    String fileName = file.getName();
                    if (file.isFile()) {
                        String className = getClassName(packageName, fileName);
                        Class<?> cls = Class.forName(className);
                        if (cls.isAnnotationPresent(annotationClass)) {
                            classList.add(cls);
                        }
                    } else {
                        String subPackagePath = getSubPackagePath(packagePath, fileName);
                        String subPackageName = getSubPackageName(packageName, fileName);
                        addClassByAnnotation(classList, subPackagePath, subPackageName, annotationClass);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章

  • springcloud之自定義簡易消費服務(wù)組件

    springcloud之自定義簡易消費服務(wù)組件

    這篇文章主要介紹了springcloud之自定義簡易消費服務(wù)組件,本篇來使用rest+ribbon消費服務(wù),并且通過輪詢方式來自定義了個簡易消費組件,感興趣的小伙伴們可以參考一下
    2018-06-06
  • Springboot搭建JVM監(jiān)控(Springboot + Prometheus + Grafana)

    Springboot搭建JVM監(jiān)控(Springboot + Prometheus +&n

    在應(yīng)用開發(fā)時,監(jiān)控報警必不可少,本文主要介紹了Springboot搭建JVM監(jiān)控(Springboot + Prometheus + Grafana),具有一定的參考價值,感興趣的可以了解一下
    2024-05-05
  • JAVA?OOM內(nèi)存溢出問題深入解析

    JAVA?OOM內(nèi)存溢出問題深入解析

    這篇文章主要為大家介紹了JAVA?OOM內(nèi)存溢出問題深入解析,在生產(chǎn)環(huán)境搶修中,我們經(jīng)常會碰到應(yīng)用系統(tǒng)java內(nèi)存OOM的情況,這個問題非常常見,今天我們就這個問題來深入學(xué)習(xí)探討一下
    2023-10-10
  • Mybatis中動態(tài)SQL,if,where,foreach的使用教程詳解

    Mybatis中動態(tài)SQL,if,where,foreach的使用教程詳解

    MyBatis的動態(tài)SQL是基于OGNL表達式的,它可以幫助我們方便的在SQL語句中實現(xiàn)某些邏輯。這篇文章主要介紹了Mybatis中動態(tài)SQL,if,where,foreach的使用教程,需要的朋友可以參考下
    2017-11-11
  • 通過Java實現(xiàn)自己動手寫ls命令

    通過Java實現(xiàn)自己動手寫ls命令

    在前面的文章中,我們仔細的介紹了關(guān)于ls命令的使用和輸出結(jié)果,在本篇文章當中我們用Java代碼自己實現(xiàn)ls命令,更加深入的了解ls命令
    2022-10-10
  • 基于Eclipse 的JSP/Servlet的開發(fā)環(huán)境的搭建(圖文)

    基于Eclipse 的JSP/Servlet的開發(fā)環(huán)境的搭建(圖文)

    本文將會詳細地展示如何搭建JSP的開發(fā)環(huán)境。本次教程使用的是最新版的Eclipse 2018-09編輯器和最新版的Apache Tomcat v9.0,步驟詳細,內(nèi)容詳盡,適合零基礎(chǔ)學(xué)者作為學(xué)習(xí)參考
    2018-12-12
  • Spring Cloud Feign簡單使用詳解

    Spring Cloud Feign簡單使用詳解

    本篇文章主要介紹了Spring Cloud Feign簡單使用詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-02-02
  • Java里得到00:00:00格式的時分秒的Timestamp

    Java里得到00:00:00格式的時分秒的Timestamp

    Java里如何得到00:00:00格式的時分秒的Timestamp ,下面是具體的實現(xiàn)代碼,需要的朋友可以參考下。
    2009-09-09
  • Maven 錯誤找不到符號的解決方法

    Maven 錯誤找不到符號的解決方法

    這篇文章主要介紹了Maven 錯誤找不到符號的解決方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • 記一次Maven項目改造成SpringBoot項目的過程實踐

    記一次Maven項目改造成SpringBoot項目的過程實踐

    本文主要介紹了Maven項目改造成SpringBoot項目的過程實踐,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03

最新評論