Java 掃描工具類(基於接口、注解掃描)


java通過反射的類掃描工具類,通過遍歷類的字節碼,找到目標文件,通過反射實例化,目標類,可以通過接口和注解兩種方式進行掃描。

package com.csnt.scdp.bizmodules.modules.util;



import java.io.File;

import java.io.IOException;

import java.net.JarURLConnection;

import java.net.URL;

import java.nio.file.*;

import java.nio.file.attribute.BasicFileAttributes;

import java.util.ArrayList;

import java.util.Enumeration;

import java.util.List;

import java.util.Objects;

import java.util.jar.JarEntry;

import java.util.jar.JarFile;

import java.util.stream.Collectors;



/**

* @Description: 類加載工具類,用來掃描各種各樣你幻想中的。。

*

* @author qcsy

* @Copyright qcsy studio

* @date 2020/07/31.

*/

public class ClassUtil {

/**

* 類名后綴

*/

private static final String class_suffix=".class";



/**

* 根據類接口查到所有的class

* @param clazz 接口文件

* @return class

*/

public static <T> List<Class<T>> getAllClassByInterface(Class<T> clazz) {

List<Class<T>> list = new ArrayList<>();

try {

List<Class> allClass = getAllClass(clazz.getPackage().getName());

/**

* 循環判斷路徑下的所有類是否實現了指定的接口 並且排除接口類自己

*/

for (int i = 0; i < allClass.size(); i++) {

if (clazz.isAssignableFrom(allClass.get(i))) {

if (!clazz.equals(allClass.get(i))) {

// 自身並不加進去

list.add(allClass.get(i));

}

}

}

} catch (Exception e) {

throw new RuntimeException(e);

}

return list;

}

/**

* 根據類接口查到所有的class

* @param clazz 接口文件

* @return class

*/

public static List<Class> getAllClassByAnnotation(Class clazz) {

try {

List<Class> allClass = getAllClass(clazz.getPackage().getName());

return allClass.stream().filter((a)->{return a.isAnnotationPresent(clazz);}).collect(Collectors.toList());

} catch (Exception e) {

throw new RuntimeException(e);

}

}

/**

* 根據類接口查到所有的class(指定包名)

* @param clazz 接口文件

* @return class

*/

public static List<Class> getAllClassByAnnotation(Class clazz,String packageName) {

try {

List<Class> allClass = getAllClass(packageName);

return allClass.stream().filter((a)->{return a.isAnnotationPresent(clazz);}).collect(Collectors.toList());

} catch (Exception e) {

throw new RuntimeException(e);

}

}

/**

* 從一個指定路徑下查找所有的類

*

* @param packagename

*/

private static List<Class> getAllClass(String packagename) {

List<String> classNameList = getClassPathsByPackage(packagename);

List<Class> list=classNameList.stream().map((b)->{

try {

return Class.forName(b);

} catch (Throwable e) {

return null;

}

}).filter(Objects::nonNull).distinct().collect(Collectors.toList());

return list;

}



/**

* 獲取某包下所有類

* @param packageName 包名

* @return 類的完整名稱

*/

public static List<String> getClassPathsByPackage(String packageName) {

List<String> fileNames = null;

ClassLoader loader = Thread.currentThread().getContextClassLoader();

String packagePath = packageName.replace(".", "/");

URL url = loader.getResource(packagePath);

if (url != null) {

String type = url.getProtocol();

if (type.equals("file")) {

String fileSearchPath = url.getPath();

fileSearchPath = fileSearchPath.substring(0,fileSearchPath.indexOf("/classes"));

fileNames = getClassPathsByFile(fileSearchPath);

} else if (type.equals("jar")) {

try{

JarURLConnection jarURLConnection = (JarURLConnection)url.openConnection();

JarFile jarFile = jarURLConnection.getJarFile();

fileNames = getClassPathsByJar(jarFile);

}catch (IOException e){

throw new RuntimeException("open Package URL failed:"+e.getMessage());

}

}else{

throw new RuntimeException("file system not support! cannot load MsgProcessor!");

}

}

return fileNames;

}



/**

* 從項目文件獲取某包下所有類

* @param filePath 文件路徑

* @return 類的完整名稱

*/

private static List<String> getClassPathsByFile(String filePath) {

List<String> classPaths = new ArrayList<String>();

try {

Files.walkFileTree(Paths.get(new File(filePath).getAbsolutePath()), new SimpleFileVisitor<Path>() {

@Override

public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {

String filePath=file.toFile().getPath();

if (filePath.endsWith(class_suffix)) {

filePath = filePath.substring(filePath.indexOf(File.separator+"classes") + 9, filePath.lastIndexOf("."));

filePath = filePath.replace(File.separator, ".").replace("/",".").replace("\\",".");

classPaths.add(filePath);

}

return super.visitFile(file, attrs);

}

});

} catch (Exception e) {

throw new RuntimeException("walk files error!",e);

}

return classPaths;

}



/**

* 從jar獲取某包下所有類

* @return 類的完整名稱

*/

private static List<String> getClassPathsByJar(JarFile jarFile) {

List<String> myClassName = new ArrayList<String>();

try {

Enumeration<JarEntry> entrys = jarFile.entries();

while (entrys.hasMoreElements()) {

JarEntry jarEntry = entrys.nextElement();

String entryName = jarEntry.getName();

if (entryName.endsWith(class_suffix)) {

entryName = entryName.replace(File.separator, ".").replace("/",".").replace("\\",".").substring(0, entryName.lastIndexOf("."));

myClassName.add(entryName);

}

}

} catch (Exception e) {

throw new RuntimeException("發生異常:"+e.getMessage());

}

return myClassName;

}



}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM