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;
}
}