溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

使用java怎么掃描指定包下的類

發(fā)布時(shí)間:2021-04-19 16:30:06 來(lái)源:億速云 閱讀:682 作者:Leah 欄目:開(kāi)發(fā)技術(shù)

本篇文章給大家分享的是有關(guān)使用java怎么掃描指定包下的類,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。

Java可以用來(lái)干什么

Java主要應(yīng)用于:1. web開(kāi)發(fā);2. Android開(kāi)發(fā);3. 客戶端開(kāi)發(fā);4. 網(wǎng)頁(yè)開(kāi)發(fā);5. 企業(yè)級(jí)應(yīng)用開(kāi)發(fā);6. Java大數(shù)據(jù)開(kāi)發(fā);7.游戲開(kāi)發(fā)等。

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

首先,比較簡(jiǎn)單的是得到我們自己寫的類,我們先來(lái)完成這個(gè),

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

使用java怎么掃描指定包下的類

我故意創(chuàng)建了這么個(gè)比較復(fù)雜的項(xiàng)目結(jié)構(gòu),現(xiàn)在我們就來(lái)獲取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)換為路徑,首先得到項(xiàng)目的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));
        //這個(gè)時(shí)候我們已經(jīng)得到了指定包下所有的類的絕對(duì)路徑了。我們現(xiàn)在利用這些絕對(duì)路徑和java的反射機(jī)制得到他們的類對(duì)象
        for (String s : classPaths) {
            //把 D:\work\code\20170401\search-class\target\classes\com\baibin\search\a\A.class 這樣的絕對(duì)路徑轉(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);
        }
    }
    /**
     * 該方法會(huì)得到所有的類,將類的絕對(duì)路徑寫入到classPaths中
     * @param file
     */
    private void doPath(File file) {
        if (file.isDirectory()) {//文件夾
            //文件夾我們就遞歸
            File[] files = file.listFiles();
            for (File f1 : files) {
                doPath(f1);
            }
        } else {//標(biāo)準(zhǔn)文件
            //標(biāo)準(zhǔn)文件我們就判斷是否是class文件
            if (file.getName().endsWith(".class")) {
                //如果是class文件我們就放入我們的集合中。
                classPaths.add(file.getPath());
            }
        }
    }
}

效果如下:

使用java怎么掃描指定包下的類

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

但是還是有辦法的。

jar中的類如何獲取:

jar下的類我們可以通過(guò)JarURLConnection類來(lái)或者,代碼如下:

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";
        //通過(guò)當(dāng)前線程得到類加載器從而得到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文件下面的類實(shí)體
                        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();
                            //這里我們需要過(guò)濾不是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);
                            }
                        }
                    }
                }
            }
        }
    }
}

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

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

補(bǔ)充:獲取指定包名下的所有類

寫了一個(gè)工具類,用于獲取指定包名下的所有類,支持遞歸遍歷,支持注解過(guò)濾,可從 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ù)注解進(jìn)行過(guò)濾)
    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();
        }
    }
}

以上就是使用java怎么掃描指定包下的類,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI