日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

詳解Java 包掃描實現和應用(Jar篇)

瀏覽:2日期:2022-08-28 10:46:19

如果你曾經使用過 Spring, 那你已經配過 包掃描路徑吧,那包掃描是怎么實現的呢?讓我們自己寫個包掃描

上篇文章中介紹了使用 File 遍歷的方式去進行包掃描,這篇主要補充一下jar包的掃描方式,在我們的項目中一般都會去依賴一些其他jar 包,

比如添加 guava 依賴

<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>28.2-jre</version></dependency>

我們再次運行上次的測試用例

@Testpublic void testGetPackageAllClasses() throws IOException, ClassNotFoundException { ClassScanner scanner = new ClassScanner('com.google.common.cache', true, null, null); Set<Class<?>> packageAllClasses = scanner.doScanAllClasses(); packageAllClasses.forEach(it -> { System.out.println(it.getName()); });}

什么都沒有輸出

依賴的 Jar

基于Java 的反射機制,我們很容易根據 class 去創建一個實例對象,但如果我們根本不知道某個包下有多少對象時,我們應該怎么做呢?

在使用Spring框架時,會根據包掃描路徑來找到所有的 class, 并將其實例化后存入容器中。

在我們的項目中也會遇到這樣的場景,比如某個包為 org.example.plugins, 這個里面放著所有的插件,為了不每次增減插件都要手動修改代碼,我們可能會想到用掃描的方式去動態獲知 org.example.plugins 到底有多少 class, 當然應用場景很有很多

思路

既然知道是采用了 jar , 那我們使用遍歷 jar 的方式去處理一下

JarFile jar = ((JarURLConnection) url.openConnection()).getJarFile();// 遍歷jar包中的元素Enumeration<JarEntry> entries = jar.entries();while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String name = entry.getName();}

這里獲取的name 格式為 com/google/common/cache/Cache.class 是不是和上篇的文件路徑很像呀, 這里可以通過對 name 進行操作獲取包名和 class

// 獲取包名String jarPackageName = name.substring(0, name.lastIndexOf(’/’)).replace('/', '.');// 獲取 class 路徑, 這樣就能通過類加載進行加載了String className = name.replace(’/’, ’.’);className = className.substring(0, className.length() - 6);

完整代碼

private void doScanPackageClassesByJar(String basePackage, URL url, Set<Class<?>> classes) throws IOException, ClassNotFoundException { // 包名 String packageName = basePackage; // 獲取文件路徑 String basePackageFilePath = packageName.replace(’.’, ’/’); // 轉為jar包 JarFile jar = ((JarURLConnection) url.openConnection()).getJarFile(); // 遍歷jar包中的元素 Enumeration<JarEntry> entries = jar.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String name = entry.getName(); // 如果路徑不一致,或者是目錄,則繼續 if (!name.startsWith(basePackageFilePath) || entry.isDirectory()) { continue; } // 判斷是否遞歸搜索子包 if (!recursive && name.lastIndexOf(’/’) != basePackageFilePath.length()) { continue; } if (packagePredicate != null) { String jarPackageName = name.substring(0, name.lastIndexOf(’/’)).replace('/', '.'); if (!packagePredicate.test(jarPackageName)) { continue; } } // 判定是否符合過濾條件 String className = name.replace(’/’, ’.’); className = className.substring(0, className.length() - 6); // 用當前線程的類加載器加載類 Class<?> loadClass = Thread.currentThread().getContextClassLoader().loadClass(className); if (classPredicate == null || classPredicate.test(loadClass)) { classes.add(loadClass); } }}

在結合上篇中 File 掃描方式就是完成的代碼了

整合后代碼

package org.example;import java.io.File;import java.io.FileFilter;import java.io.IOException;import java.net.JarURLConnection;import java.net.URL;import java.net.URLDecoder;import java.util.Enumeration;import java.util.LinkedHashSet;import java.util.Set;import java.util.function.Predicate;import java.util.jar.JarEntry;import java.util.jar.JarFile;/** * class 掃描器 * * @author zhangyunan */public class ClassScanner { private final String basePackage; private final boolean recursive; private final Predicate<String> packagePredicate; private final Predicate<Class> classPredicate; /** * Instantiates a new Class scanner. * * @param basePackage the base package * @param recursive 是否遞歸掃描 * @param packagePredicate the package predicate * @param classPredicate the class predicate */ public ClassScanner(String basePackage, boolean recursive, Predicate<String> packagePredicate, Predicate<Class> classPredicate) { this.basePackage = basePackage; this.recursive = recursive; this.packagePredicate = packagePredicate; this.classPredicate = classPredicate; } /** * Do scan all classes set. * * @return the set * @throws IOException the io exception * @throws ClassNotFoundException the class not found exception */ public Set<Class<?>> doScanAllClasses() throws IOException, ClassNotFoundException { Set<Class<?>> classes = new LinkedHashSet<Class<?>>(); String packageName = basePackage; // 如果最后一個字符是“.”,則去掉 if (packageName.endsWith('.')) { packageName = packageName.substring(0, packageName.lastIndexOf(’.’)); } // 將包名中的“.”換成系統文件夾的“/” String basePackageFilePath = packageName.replace(’.’, ’/’); Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(basePackageFilePath); while (resources.hasMoreElements()) { URL resource = resources.nextElement(); String protocol = resource.getProtocol(); if ('file'.equals(protocol)) { String filePath = URLDecoder.decode(resource.getFile(), 'UTF-8'); // 掃描文件夾中的包和類 doScanPackageClassesByFile(classes, packageName, filePath); } else if ('jar'.equals(protocol)) { doScanPackageClassesByJar(packageName, resource, classes); } } return classes; } private void doScanPackageClassesByJar(String basePackage, URL url, Set<Class<?>> classes) throws IOException, ClassNotFoundException { // 包名 String packageName = basePackage; // 獲取文件路徑 String basePackageFilePath = packageName.replace(’.’, ’/’); // 轉為jar包 JarFile jar = ((JarURLConnection) url.openConnection()).getJarFile(); // 遍歷jar包中的元素 Enumeration<JarEntry> entries = jar.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String name = entry.getName(); // 如果路徑不一致,或者是目錄,則繼續 if (!name.startsWith(basePackageFilePath) || entry.isDirectory()) { continue; } // 判斷是否遞歸搜索子包 if (!recursive && name.lastIndexOf(’/’) != basePackageFilePath.length()) { continue; } if (packagePredicate != null) { String jarPackageName = name.substring(0, name.lastIndexOf(’/’)).replace('/', '.'); if (!packagePredicate.test(jarPackageName)) { continue; } } // 判定是否符合過濾條件 String className = name.replace(’/’, ’.’); className = className.substring(0, className.length() - 6); // 用當前線程的類加載器加載類 Class<?> loadClass = Thread.currentThread().getContextClassLoader().loadClass(className); if (classPredicate == null || classPredicate.test(loadClass)) { classes.add(loadClass); } } } /** * 在文件夾中掃描包和類 */ private void doScanPackageClassesByFile(Set<Class<?>> classes, String packageName, String packagePath) throws ClassNotFoundException { // 轉為文件 File dir = new File(packagePath); if (!dir.exists() || !dir.isDirectory()) { return; } // 列出文件,進行過濾 // 自定義文件過濾規則 File[] dirFiles = dir.listFiles((FileFilter) file -> { String filename = file.getName(); if (file.isDirectory()) { if (!recursive) { return false; } if (packagePredicate != null) { return packagePredicate.test(packageName + '.' + filename); } return true; } return filename.endsWith('.class'); }); if (null == dirFiles) { return; } for (File file : dirFiles) { if (file.isDirectory()) { // 如果是目錄,則遞歸 doScanPackageClassesByFile(classes, packageName + '.' + file.getName(), file.getAbsolutePath()); } else { // 用當前類加載器加載 去除 fileName 的 .class 6 位 String className = file.getName().substring(0, file.getName().length() - 6); Class<?> loadClass = Thread.currentThread().getContextClassLoader().loadClass(packageName + ’.’ + className); if (classPredicate == null || classPredicate.test(loadClass)) { classes.add(loadClass); } } } }}

到此這篇關于詳解Java 包掃描實現和應用(Jar篇)的文章就介紹到這了,更多相關Java 包掃描實現和應用內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
99pao成人国产永久免费视频 | 中文不卡在线| 成人日韩精品| 久久99精品久久久久久园产越南| 日本欧美在线| 亚洲精品精选| 亚洲综合福利| 国产综合亚洲精品一区二| 亚洲成av在线| 国产精品99久久免费| 国产精品.xx视频.xxtv| 欧美一区二区三区久久| 日韩国产欧美一区二区三区| 亚洲专区视频| 国产一区二区视频在线看| 高潮久久久久久久久久久久久久| 日本不卡免费高清视频在线| 久久精品成人| 性欧美xxxx免费岛国不卡电影| 久久亚洲国产| 日韩午夜一区| 国产精品一线天粉嫩av| 国产精品男女| 欧美日韩视频| 午夜久久av| 欧美特黄一区| 国产精一区二区| 日本欧美一区| 色综合视频一区二区三区日韩| 国产精品毛片aⅴ一区二区三区| 精品精品99| 日本在线成人| 亚洲天堂1区| 国产伊人精品| 国产精品色婷婷在线观看| 国产日韩视频| 九一精品国产| 亚洲无线观看| 日韩欧美少妇| 亚洲免费观看高清完整版在线观| 国产精品免费不| 免费黄色成人| 色婷婷色综合| 国产专区精品| 天堂av在线一区| 99国产精品99久久久久久粉嫩| 国产欧美日韩| 日本 国产 欧美色综合| 国产精品一区二区中文字幕| 亚洲欧美日韩在线观看a三区| 国产一区二区三区亚洲| 欧美亚洲一区二区三区| 日韩视频在线一区二区三区| 97欧美在线视频| 国产毛片精品久久| 亚洲人成亚洲精品| 亚洲精品极品少妇16p| 黄色aa久久| 你懂的网址国产 欧美| 日韩av不卡在线观看| 蜜臀av国产精品久久久久| 日韩精品欧美激情一区二区| а√天堂8资源中文在线| 日韩综合精品| 国产精品22p| 麻豆国产精品视频| 国产探花在线精品一区二区| 亚洲色图网站| 日韩一区二区三区精品视频第3页| 日韩专区欧美专区| 蜜桃视频第一区免费观看| 国产美女精品| 玖玖精品视频| 综合亚洲色图| 久久不卡日韩美女| 日韩av片子| 国产综合精品| 亚洲午夜国产成人| 美国欧美日韩国产在线播放| 蜜桃视频一区二区| 国产亚洲精品美女久久| 国产欧美在线| 日韩精品第一区| 亚洲电影在线一区二区三区| 亚洲欧洲一区二区天堂久久| 中文字幕免费一区二区| 国产精品久久久久久模特| 欧美国产日本| 欧美日韩中文一区二区| 香蕉久久国产| 开心激情综合| 狠狠爱www人成狠狠爱综合网| 亚洲开心激情| 高清不卡一区| 亚洲一二三区视频| 欧美久久天堂| 国产一卡不卡| 午夜亚洲一区| 青青青免费在线视频| 午夜宅男久久久| 国产精品久久久久77777丨| 成人污污视频| 日韩av一二三| 日本欧美不卡| 日韩欧美高清一区二区三区| 麻豆国产精品一区二区三区| 久久久噜噜噜| 婷婷久久免费视频| 国产成人在线中文字幕| 久久久久久久久99精品大| 91久久中文| 另类综合日韩欧美亚洲| 久久女人天堂| 91精品国产自产观看在线| 日韩欧美综合| 国产日本精品| 香蕉久久久久久久av网站| 免费在线成人| 亚洲一区免费| 国产一区二区三区精品在线观看| 99pao成人国产永久免费视频 | 美女网站久久| 色综合五月天| 亚洲欧美日本日韩| 日韩伦理福利| 精品福利久久久| 狠狠久久婷婷| 捆绑调教日本一区二区三区| 免费在线日韩av| 久久国产欧美日韩精品| 日韩影片在线观看| 午夜久久美女| 国产传媒在线| 国产精品xxxav免费视频| 激情综合自拍| 欧美成人精品| 欧美精品高清| 欧洲精品一区二区三区| 麻豆精品视频在线| 欧美日韩国产一区精品一区| 亚洲国产综合在线看不卡| 精品在线网站观看| 亚洲欧美激情诱惑| 波多野结衣久久精品| 亚洲精品第一| 免费不卡中文字幕在线| 国产精品一区二区中文字幕| 亚洲欧洲另类| 精品欧美日韩精品| 亚洲九九精品| 亚洲精品2区| 91欧美在线| 麻豆精品久久| 国产图片一区| 日韩美女国产精品| 国产精品日韩| 好看不卡的中文字幕| 日韩免费福利视频| 久久久久九九精品影院| 青青青国产精品| 色爱综合av| 99久久精品网| 国产剧情一区二区在线观看| 国产调教精品| 亚洲成人va| 亚洲精品极品少妇16p| 99久久99视频只有精品| 五月精品视频| 欧美激情另类| 欧美日韩va| 久久的色偷偷| 天使萌一区二区三区免费观看| 亚洲一区av| 国产成人精品福利| 久久国产88| 波多野结衣久久精品| 国产亚洲精品自拍| 国产欧美久久一区二区三区| 丁香婷婷久久| 日韩一区精品视频| 国产精品亲子伦av一区二区三区| 日韩电影免费网站| 午夜在线精品偷拍| 美女久久99| 亚洲精品一级| 日韩和的一区二在线| 亚洲人www| 午夜在线视频观看日韩17c| 国产精品xx| 久久av导航| 视频一区欧美精品| 亚洲人成在线网站| 国产日韩精品视频一区二区三区| 亚洲va中文在线播放免费| 亚洲午夜免费| 亚洲二区三区不卡| 少妇精品导航| 日韩电影在线视频| 欧美成人基地| 激情久久久久久|