Java如何掃描指定package下所有的類
在寫一個MVC框架,需要從包中掃描出元件並註冊到容器中,而JDK沒有提供現成的從方法,只能自己實現。
功能:
給定一個包名,程式設計得到該包(和其所有子包)下所有的類檔案。如,輸入包名com.myapp.util
, 輸出該包下類的全限定名com.myapp.util.StringUtils
, com.app.util.ImageUtils
等。
思路:
有的web server在部署執行時會解壓jar包,因此class檔案會在普通的檔案目錄下。如果web server不解壓jar包,則class檔案會直接存在於Jar包中。對於前者,只需定位到class檔案所在目錄,然後將class檔名讀取出即可;對於後者,則需先定位到jar包所在目錄,然後使用JarInputStream
實現:
這是從寫好的專案程式碼中直接copy出來的,如果要執行這段程式碼,需要把所有的Logger.debug
改成System.out.println()
/**
* This scanner is used to find out all classes in a package.
* Created by whf on 15-2-26.
*/
public class ClasspathPackageScanner implements PackageScanner {
private Logger logger = LoggerFactory.getLogger(ClasspathPackageScanner.class);
private String basePackage;
private ClassLoader cl;
/**
* Construct an instance and specify the base package it should scan.
* @param basePackage The base package to scan.
*/
public ClasspathPackageScanner(String basePackage) {
this.basePackage = basePackage;
this.cl = getClass().getClassLoader();
}
/**
* Construct an instance with base package and class loader.
* @param basePackage The base package to scan.
* @param cl Use this class load to locate the package.
*/
public ClasspathPackageScanner(String basePackage, ClassLoader cl) {
this.basePackage = basePackage;
this.cl = cl;
}
/**
* Get all fully qualified names located in the specified package
* and its sub-package.
*
* @return A list of fully qualified names.
* @throws IOException
*/
@Override
public List<String> getFullyQualifiedClassNameList() throws IOException {
logger.info("開始掃描包{}下的所有類", basePackage);
return doScan(basePackage, new ArrayList<>());
}
/**
* Actually perform the scanning procedure.
*
* @param basePackage
* @param nameList A list to contain the result.
* @return A list of fully qualified names.
*
* @throws IOException
*/
private List<String> doScan(String basePackage, List<String> nameList) throws IOException {
// replace dots with splashes
String splashPath = StringUtil.dotToSplash(basePackage);
// get file path
URL url = cl.getResource(splashPath);
String filePath = StringUtil.getRootPath(url);
// Get classes in that package.
// If the web server unzips the jar file, then the classes will exist in the form of
// normal file in the directory.
// If the web server does not unzip the jar file, then classes will exist in jar file.
List<String> names = null; // contains the name of the class file. e.g., Apple.class will be stored as "Apple"
if (isJarFile(filePath)) {
// jar file
if (logger.isDebugEnabled()) {
logger.debug("{} 是一個JAR包", filePath);
}
names = readFromJarFile(filePath, splashPath);
} else {
// directory
if (logger.isDebugEnabled()) {
logger.debug("{} 是一個目錄", filePath);
}
names = readFromDirectory(filePath);
}
for (String name : names) {
if (isClassFile(name)) {
//nameList.add(basePackage + "." + StringUtil.trimExtension(name));
nameList.add(toFullyQualifiedName(name, basePackage));
} else {
// this is a directory
// check this directory for more classes
// do recursive invocation
doScan(basePackage + "." + name, nameList);
}
}
if (logger.isDebugEnabled()) {
for (String n : nameList) {
logger.debug("找到{}", n);
}
}
return nameList;
}
/**
* Convert short class name to fully qualified name.
* e.g., String -> java.lang.String
*/
private String toFullyQualifiedName(String shortName, String basePackage) {
StringBuilder sb = new StringBuilder(basePackage);
sb.append('.');
sb.append(StringUtil.trimExtension(shortName));
return sb.toString();
}
private List<String> readFromJarFile(String jarPath, String splashedPackageName) throws IOException {
if (logger.isDebugEnabled()) {
logger.debug("從JAR包中讀取類: {}", jarPath);
}
JarInputStream jarIn = new JarInputStream(new FileInputStream(jarPath));
JarEntry entry = jarIn.getNextJarEntry();
List<String> nameList = new ArrayList<>();
while (null != entry) {
String name = entry.getName();
if (name.startsWith(splashedPackageName) && isClassFile(name)) {
nameList.add(name);
}
entry = jarIn.getNextJarEntry();
}
return nameList;
}
private List<String> readFromDirectory(String path) {
File file = new File(path);
String[] names = file.list();
if (null == names) {
return null;
}
return Arrays.asList(names);
}
private boolean isClassFile(String name) {
return name.endsWith(".class");
}
private boolean isJarFile(String name) {
return name.endsWith(".jar");
}
/**
* For test purpose.
*/
public static void main(String[] args) throws Exception {
PackageScanner scan = new ClasspathPackageScanner("cn.fh.lightning.bean");
scan.getFullyQualifiedClassNameList();
}
}
上面的程式碼中用到了StringUtils
類,如下:
public class StringUtil {
private StringUtil() {
}
/**
* "file:/home/whf/cn/fh" -> "/home/whf/cn/fh"
* "jar:file:/home/whf/foo.jar!cn/fh" -> "/home/whf/foo.jar"
*/
public static String getRootPath(URL url) {
String fileUrl = url.getFile();
int pos = fileUrl.indexOf('!');
if (-1 == pos) {
return fileUrl;
}
return fileUrl.substring(5, pos);
}
/**
* "cn.fh.lightning" -> "cn/fh/lightning"
* @param name
* @return
*/
public static String dotToSplash(String name) {
return name.replaceAll("\\.", "/");
}
/**
* "Apple.class" -> "Apple"
*/
public static String trimExtension(String name) {
int pos = name.indexOf('.');
if (-1 != pos) {
return name.substring(0, pos);
}
return name;
}
/**
* /application/home -> /home
* @param uri
* @return
*/
public static String trimURI(String uri) {
String trimmed = uri.substring(1);
int splashIndex = trimmed.indexOf('/');
return trimmed.substring(splashIndex);
}
}
執行結果:
相關推薦
Java如何掃描指定package下所有的類
在寫一個MVC框架,需要從包中掃描出元件並註冊到容器中,而JDK沒有提供現成的從方法,只能自己實現。 功能: 給定一個包名,程式設計得到該包(和其所有子包)下所有的類檔案。如,輸入包名com.myapp.util, 輸出該包下類的全限定名com.myapp.
java讀取指定package下的所有class
public als sta 功能 accept smo bstr 文件的 get JAVA如何掃描一個包下面的所有類,並加載到內存中去? spring中有一個<context:component-scan base-package="com.controller"
java 遍歷指定包下所有類,返回完整類名。工具類,可以直接拷入使用
1、說明: 此類為本人開發的工具類,具體應用在什麼地方呢。本人在實際專案中,許可權管理這一塊有所應用,應該是許可權這一塊有所需求而開發的。 應用場景說明:許可權資源自動化生產時,使用者點選介面的一鍵生成資源時,介面中就會遍歷指定controller包下所有
掃描指定目錄下所有圖片文件
沒有 extern wpa gets 當前 indexof path resolv cti String myparent=newPath.substring(0, newPath.lastIndexOf("/")).substring(newPath.substrin
Java 掃描指定包下的檔案
第一種方法:利用google的guava掃描指定的包 StringBuffer value = new StringBuffer(); String packageName = "com.business.service.impl"; ClassPath classpat
java 獲取指定目錄下所有檔案的名稱
需要將檔名稱及路徑存到資料庫中 String path ="/db/java/Data3/"; StringBuffer str = new StringBuffer(""); File
掃描指定目錄下所有圖片檔案
<span style="font-size:18px;"> String myparent=newPath.substring(0, newPath.lastIndexOf("/")).substring(newPath.substrin
Java 掃描包下所有類(包括jar包)
package com.MyUtils.file;import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.net.JarURLConnection; i
Java 列出資料夾下所有檔案,符合條件的檔案複製到指定目錄
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; public class TestFile { public static void main(String[] a
史上最完整掃描包下所有類(含Jar包掃描,maven子專案掃描)
要掃描包下的所有類,分類路徑下掃描和jar包掃描兩種,其中jar包掃描又分專案中引入的三方jar包,同級maven的多個子專案jar相互引用,還有jdk jar包(這裡不考慮,一般沒哪個專案會掃描jdk jar包裡的類). 我先宣告一個介面,用於應對不同型別的class
java程式 一次改變指定目錄下所有檔案編碼(包括子目錄中的檔案)
package transCoding; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInpu
Java 替換資料夾下所有檔案中指定的內容
我的上一篇部落格提到了找到檔案中的中文。之前的程式碼還可以做一個擴充套件。可以作為一個強大的查詢功能使用。關鍵字查詢,這個功能大家可以思考一下,今後我的部落格也會去貼上這樣的關鍵字查詢的功能的程式碼,能跟大家討論分析一下。 今天的替換的功能也是基於上篇
JAVA獲取同一路徑下所有子類或介面實現類
整個測試程式碼如下: Java程式碼 package find; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.A
獲取包下所有類中的註解的值 (java工具類)
作用:這個工具類主要的作用就是獲取類中的註解的值。 應用場景:做許可權的時候獲取@RequestMapping();的值,自動新增到資料庫中。 /** * getRequestMappingValue方法描述: * 作者:thh
java找到資料夾下所有的指定格式檔案並輸出到txt
import java.io.*; public class CopyDirsMain { /** * 注意,pw初始化不能在遞迴裡面。在遞迴時可能會出錯 * * */ public static void main(String[] args) {
Java呼叫在default package下的類
今天工作的時候,遇到一個坑,寫一個功能需要呼叫dll的檔案,然後硬體方提供的API的程式程式碼是需要把他們的讀取資料的程式碼放在default package,但是我需要在其他包名在呼叫,普通的呼叫和匯入都不行,就只能通過反射來呼叫。 通過反射即可呼叫defa
抓取指定路徑下所有文檔名
mds 所有 -- 2.6 div ast txt rom char --方法1: EXEC xp_dirtree ‘\\172.6.6.6\D$\TEXT\‘,1,1 --方法2: CREATE TABLE #TXT_Name (NAME VARCHAR( 2000)
掃描指定路徑下的全部請求路徑(基於SpringMVC)
ada access cto url ssm private 博客 ble ack 通過上面兩篇博客,我們能夠得到指定類上的全部請求路徑。現在需要的是,給定一個指定的路徑,獲取全部的請求路徑。 public class RequestUrlScannerHelper {
Java遍歷包中所有類方法註解
|| asm 服務器 ret nec next 代碼 自定義 tco 一.代碼實例 import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.l
Java基礎知識-java.util.concurrent包下常見類的使用
finall iss con value 通信 out 否則 app ted 一,Condition 一個場景,兩個線程數數,同時啟動兩個線程,線程A數1、2、3,然後線程B數4、5、6,最後線程A數7、8、9,程序結束,這涉及到線程之間的通信。 public class