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

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

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

瀏覽:17日期: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久久,三上悠亚国产精品一区二区三区
黄色日韩在线| 99在线精品免费视频九九视| 中文字幕日本一区| 日本韩国欧美超级黄在线观看| 日韩av有码| 午夜久久中文| 日韩在线欧美| 久久中文亚洲字幕| 伊人久久亚洲美女图片| 老鸭窝亚洲一区二区三区| 国产精品大片免费观看| 美女精品视频在线| 国产成人精选| 精精国产xxxx视频在线野外| 久久九九99| 老鸭窝毛片一区二区三区| 999在线观看精品免费不卡网站| 99国产精品久久久久久久| 午夜精品影院| 综合精品一区| 欧美日韩亚洲一区三区| 里番精品3d一二三区| 福利在线免费视频| 欧美日韩在线播放视频| 伊人国产精品| 国产精品美女在线观看直播| 国产一区二区三区精品在线观看| 日韩欧美在线中字| 午夜日韩福利| 日本视频中文字幕一区二区三区| 国产精品成人3p一区二区三区| 久久精品九色| 激情婷婷亚洲| 久久亚洲欧美| 国产乱子精品一区二区在线观看 | 视频小说一区二区| 视频一区在线视频| 国产精品日韩精品中文字幕| 国产高清不卡| 午夜亚洲精品| 麻豆精品视频在线观看免费| 久久久久国产| 亚洲精品第一| 成人亚洲一区二区| 国产视频欧美| 国产精品高清一区二区| 国产高清不卡| 中文字幕视频精品一区二区三区| 久久99精品久久久野外观看| 99久久99久久精品国产片果冰| 亚洲欧洲国产精品一区| 国产一区二区三区四区二区 | 久久久久国产精品一区三寸| 日韩中文字幕区一区有砖一区 | 精品亚洲a∨| 国产精品婷婷| 国产欧美欧美| 久久久影院免费| 日本欧美一区二区在线观看| 亚洲伦乱视频| 国产欧美高清| 国产精品91一区二区三区| 国产美女视频一区二区| 91久久在线| 欧美xxxx中国| 日韩极品在线观看| 欧美高清不卡| 精品一区电影| 日韩不卡免费视频| 99久久www免费| 免费观看亚洲天堂| 国产精品毛片一区二区在线看| 婷婷综合社区| 国产日韩欧美一区| 亚洲欧美一区在线| 精品在线网站观看| 午夜在线一区| 日韩欧美午夜| 国产精品日本一区二区三区在线 | 美日韩一区二区三区| 丝袜a∨在线一区二区三区不卡| 国产videos久久| 91久久精品无嫩草影院| 狠狠色综合网| av资源中文在线天堂| 中文字幕一区二区精品区| 亚洲风情在线资源| 国产精品网址| 日产欧产美韩系列久久99| 婷婷精品进入| 日韩欧美另类一区二区| 久久不卡日韩美女| 亚洲精品自拍| 美女网站久久| 欧美亚洲在线日韩| 波多野结衣久久精品| 久久av影院| 欧美日韩亚洲一区二区三区在线| 人人精品人人爱| 亚洲一本视频| 日韩欧美四区| 成人在线丰满少妇av| 国产日韩一区二区三区在线| 久久高清一区| 欧美日韩一二| 日韩精品永久网址| 精品视频在线观看网站| 92国产精品| 国产不卡精品| 精品精品久久| 欧美精品99| 欧美伊人久久| 日本v片在线高清不卡在线观看| 9色国产精品| 激情婷婷欧美| 99久久精品网| 婷婷激情一区| 激情亚洲影院在线观看| 日韩欧美综合| 日韩伦理一区| 午夜av成人| 九九综合九九| 免费毛片在线不卡| 伊人久久大香线蕉av超碰演员| 国产精品99免费看| 欧美福利一区| 亚洲欧美日韩国产一区| 免费成人在线视频观看| 亚洲精品乱码久久久久久蜜桃麻豆 | 国产精品.xx视频.xxtv| 国产精品一区毛片| 欧美国产免费| 精品国产aⅴ| 国产夫妻在线| 婷婷国产精品| 手机精品视频在线观看| 亚久久调教视频| 日韩精品免费观看视频| 国产日韩欧美在线播放不卡| 麻豆国产一区| 欧美国产美女| 国产伊人精品| 国产精品色网| 午夜亚洲福利| 欧美国产不卡| 在线天堂中文资源最新版| 99久精品视频在线观看视频| 国产农村妇女精品一二区| 亚洲精品影院在线观看| 国产精品美女久久久久久不卡| 日本一二区不卡| 久久久久久久久久久妇女| 国产精品人人爽人人做我的可爱| 亚洲精品自拍| 精品三级国产| 99久久精品网站| 亚洲精品精选| 老司机精品视频网| 色在线视频观看| 国产亚洲在线观看| 国产精品视频一区二区三区 | 激情丁香综合| 亚洲一级淫片| 国产成人精品亚洲线观看| 激情丁香综合| 亚洲ww精品| 国产成人在线中文字幕| 激情综合自拍| 国产日韩欧美一区二区三区在线观看| 成人国产综合| 国产精品任我爽爆在线播放| 不卡一二三区| 亚洲精品系列| 国产高潮在线| 国产精品毛片一区二区三区| 久久国际精品| 精品免费av在线| 日韩欧美二区| 日韩精选在线| 在线一区视频观看| 色综合视频一区二区三区日韩| 精品国产一区二区三区av片| 亚洲一区不卡| 国产一区精品福利| 蜜臀久久久99精品久久久久久| 国产精品久久久久9999高清 | 97精品国产| 亚洲久草在线| 国产传媒在线| 91av一区| 在线国产一区| 精品国产a一区二区三区v免费| 视频在线观看一区| 国产精品精品| 婷婷综合成人| 激情久久婷婷| 国产中文字幕一区二区三区| 午夜久久av| 免费精品国产的网站免费观看| 国产精品视频3p|