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;

}



}

 

posted @ 2022-03-25 15:44  甜菜波波  阅读(1364)  评论(0编辑  收藏  举报