com.feingto.cloud.kit.ClassKit Maven / Gradle / Ivy
package com.feingto.cloud.kit;
import com.google.common.collect.Lists;
import javassist.*;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* Class 工具类
*
* @author longfei
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public class ClassKit {
public static boolean isJavaBasicType(Class> clazz) {
return clazz != null && (clazz.isPrimitive() || Number.class.isAssignableFrom(clazz) || Character.class.isAssignableFrom(clazz) || Boolean.class.isAssignableFrom(clazz) || CharSequence.class.isAssignableFrom(clazz) || Enum.class.isAssignableFrom(clazz) || Date.class.isAssignableFrom(clazz) || Calendar.class.isAssignableFrom(clazz));
}
/**
* 判断指定的类是否为Collection(或者其子类或者其子接口)。
*
* @param clazz Class
* @return boolean
*/
public static boolean isCollection(Class> clazz) {
return clazz != null && Collection.class.isAssignableFrom(clazz);
}
/**
* 判断指定的类是否为Map(或者其子类或者其子接口)。
*
* @param clazz Class
* @return boolean
*/
public static boolean isMap(Class> clazz) {
return clazz != null && Map.class.isAssignableFrom(clazz);
}
/**
* 判断指定的类是否为Java基本类型的数组。
*
* @param clazz Class
* @return boolean
*/
public static boolean isPrimitiveArray(Class> clazz) {
return clazz != null && (clazz == byte[].class || (clazz == short[].class || (clazz == int[].class || (clazz == long[].class || (clazz == char[].class || (clazz == float[].class || (clazz == double[].class || clazz == boolean[].class)))))));
}
/**
* 判断指定的类是否为Java基本类型的数组。
*
* @param clazz Class
* @return boolean
*/
public static boolean isPrimitiveWrapperArray(Class> clazz) {
return clazz != null && (clazz == Byte[].class || (clazz == Short[].class || (clazz == Integer[].class || (clazz == Long[].class || (clazz == Character[].class || (clazz == Float[].class || (clazz == Double[].class || clazz == Boolean[].class)))))));
}
/**
* 获取包括该类本身但不包含java.lang.Object的所有超类。
*
* @param clazz Class
* @return 超类数组
*/
public static Class>[] getAllClass(Class> clazz) {
List> clazzList = new ArrayList<>();
getAllSupperClass(clazzList, clazz);
return (Class[]) clazzList.toArray(new Class[0]);
}
private static void getAllSupperClass(List> clazzList, Class> clazz) {
if (!clazz.equals(Object.class)) {
clazzList.add(clazz);
getAllSupperClass(clazzList, clazz.getSuperclass());
}
}
/**
* 获取该类所有实现的接口数组。
*
* @param clazz Class
* @return 该类所有实现的接口数组
*/
public static Class>[] getAllInterface(Class> clazz) {
List> clazzList = new ArrayList<>();
Class>[] interfaces = clazz.getInterfaces();
for (Class> interfaceClazz : interfaces) {
clazzList.add(interfaceClazz);
getAllSupperInterface(clazzList, interfaceClazz);
}
return (Class[]) clazzList.toArray(new Class[0]);
}
private static void getAllSupperInterface(List> clazzList, Class> clazz) {
if (!clazz.equals(Object.class)) {
Class>[] interfaces = clazz.getInterfaces();
for (Class> interfaceClazz : interfaces) {
clazzList.add(interfaceClazz);
getAllSupperInterface(clazzList, interfaceClazz);
}
}
}
/**
* 获取包括该类本身以及所有超类(不含java.lang.Object)和实现的接口中定义的属性。
*
* @param clazz Class
* @return 属性数组
*/
public static Field[] getAllField(Class> clazz) {
List fieldList = new ArrayList<>();
Class[] supperInterfaces = getAllClass(clazz);
for (Class> aClazz : supperInterfaces) {
fieldList.addAll(Lists.newArrayList(aClazz.getDeclaredFields()));
}
supperInterfaces = getAllInterface(clazz);
for (Class> aInterface : supperInterfaces) {
fieldList.addAll(Lists.newArrayList(aInterface.getDeclaredFields()));
}
return fieldList.toArray(new Field[0]);
}
/**
* 获取该类中所有字段
*
* @param clazz Class
* @return 属性数组
*/
public static Field[] getFields(Class> clazz) {
return new ArrayList<>(Lists.newArrayList(clazz.getDeclaredFields())).toArray(new Field[0]);
}
/**
* 得到方法参数名称和方法参数值
* 注:类里面同名方法会解析第一个
*
* @param cls 当前类
* @param clazzName 方法类名
* @param methodName 方法名
* @param args 方法参数
* @return Map
*/
public static Map getFieldMap(Class cls, String clazzName, String methodName, Object[] args) throws NotFoundException {
Map map = new HashMap<>();
ClassPool pool = ClassPool.getDefault();
ClassClassPath classPath = new ClassClassPath(cls);
pool.insertClassPath(classPath);
CtClass cc = pool.get(clazzName);
CtMethod cm = cc.getDeclaredMethod(methodName);
MethodInfo methodInfo = cm.getMethodInfo();
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
if (attr == null) {
throw new RuntimeException();
}
int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
for (int i = 0; i < cm.getParameterTypes().length; i++) {
map.put(attr.variableName(i + pos), args[i]);
}
return map;
}
/**
* 获取启用元注解clazz的全部类
*
* @param packageName 包路径
* @param clazz 元注解类
* @return 类集合
*/
public static Set> getClassesByAnnotation(String packageName, Class extends Annotation> clazz) {
Set> aClasses = new LinkedHashSet<>();
getClasses(packageName).stream().filter(clz -> clz.isAnnotationPresent(clazz)).forEach(aClasses::add);
return aClasses;
}
/**
* 从包package中获取所有的Class
*
* @param packageName 包路径
* @return Set
*/
public static Set> getClasses(String packageName) {
// 第一个class类的集合
Set> classes = new LinkedHashSet<>();
// 获取包的名字, 并进行替换
String packageDirName = packageName.replace('.', '/');
// 定义一个枚举的集合, 并进行循环来处理这个目录下的things
Enumeration dirs;
try {
dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
while (dirs.hasMoreElements()) {
URL url = dirs.nextElement();
String protocol = url.getProtocol();
// 如果是以文件的形式保存在服务器上
if ("file".equals(protocol)) {
// 获取包的物理路径
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
// 以文件的方式扫描整个包下的文件, 并添加到集合中
getClassesByPackage(packageName, filePath, true, classes);
} else if ("jar".equals(protocol)) {
// 如果是jar包文件, 定义一个JarFile
JarFile jar;
try {
// 获取jar
jar = ((JarURLConnection) url.openConnection()).getJarFile();
// 从jar包, 得到一个枚举类
Enumeration entries = jar.entries();
// 同样的进行循环迭代
while (entries.hasMoreElements()) {
// 获取jar里的一个实体, 可以是目录和一些jar包里的其他文件, 如META-INF等文件
JarEntry entry = entries.nextElement();
String name = entry.getName();
if (name.charAt(0) == '/') {
name = name.substring(1);
}
// 如果前半部分和定义的包名相同
if (name.startsWith(packageDirName)) {
int idx = name.lastIndexOf('/');
// 如果以"/"结尾, 则是一个包
if (idx != -1) {
// 获取包名, 把"/"替换成"."
packageName = name.substring(0, idx).replace('/', '.');
}
// 如果是一个.class文件, 并且不是目录
if (name.endsWith(".class") && !entry.isDirectory()) {
// 去掉后面的".class", 获取真正的类名
String className = name.substring(packageName.length() + 1, name.length() - 6);
try {
classes.add(Class.forName(packageName + '.' + className));
} catch (ClassNotFoundException e) {
// log.error("添加用户自定义视图类错误, 找不到此类的.class文件.");
e.printStackTrace();
}
}
}
}
} catch (IOException e) {
// log.error("在扫描用户定义视图时从jar包获取文件出错.");
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return classes;
}
/**
* 以文件的形式来获取包下的所有Class
*
* @param packageName 包名
* @param packagePath 包目录路径
* @param recursive 是否循环迭代
* @param classes 类集合
*/
public static void getClassesByPackage(String packageName, String packagePath, final boolean recursive, Set> classes) {
File dir = new File(packagePath);
if (dir.exists() && dir.isDirectory()) {
// 自定义过滤规则, 如果可以循环(包含子目录)或以.class结尾的文件(编译好的java类文件)
File[] dirfiles = dir.listFiles(file -> recursive && file.isDirectory() || file.getName().endsWith(".class"));
if (dirfiles != null) {
for (File file : dirfiles) {
if (file.isDirectory()) {
getClassesByPackage(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, classes);
} else {
// 如果是java类文件, 去掉后面的.class, 只留下类名
String className = file.getName().substring(0, file.getName().length() - 6);
try {
classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + '.' + className));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy