import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.io.File;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class ClassUtil {
private static LoadingCache<String, ArrayList<Class>> classCache;
static {
classCache = buildAllClassCache();
}
/**
* 获取接口上的泛型T
*
* @param o 接口
* @param index 泛型索引
*/
public static Class<?> getInterfaceT(Object o, int index) {
Type[] types = o.getClass().getGenericInterfaces();
ParameterizedType parameterizedType = (ParameterizedType) types[0];
Type type = parameterizedType.getActualTypeArguments()[index];
return checkType(type, index);
}
/**
* 获取类上的泛型T
*
* @param o 接口
* @param index 泛型索引
*/
public static Class<?> getClassT(Object o, int index) {
Type type = o.getClass().getGenericSuperclass();
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type actType = parameterizedType.getActualTypeArguments()[index];
return checkType(actType, index);
} else {
String className = type == null ? "null" : type.getClass().getName();
throw new IllegalArgumentException("Expected a Class, ParameterizedType"
+ ", but <" + type + "> is of type " + className);
}
}
private static Class<?> checkType(Type type, int index) {
if (type instanceof Class<?>) {
return (Class<?>) type;
} else if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
Type t = pt.getActualTypeArguments()[index];
return checkType(t, index);
} else {
String className = type == null ? "null" : type.getClass().getName();
throw new IllegalArgumentException("Expected a Class, ParameterizedType"
+ ", but <" + type + "> is of type " + className);
}
}
/**
* 功能描述 获取接口的所有实现类
*
* @return java.util.ArrayList<java.lang.Class>
*/
public static ArrayList<Class> getAllClassByInterface(Class clazz) {
ArrayList<Class> list = new ArrayList<>();
// 判断是否是一个接口
if (clazz.isInterface()) {
try {
ArrayList<Class> allClass = classCache.getUnchecked(clazz.getPackage().getName());
/**
* 循环判断路径下的所有类是否实现了指定的接口 并且排除接口类自己
*/
for (int i = 0; i < allClass.size(); i++) {
/**
* 判断是不是同一个接口
*/
// isAssignableFrom:判定此 Class 对象所表示的类或接口与指定的 Class
// 参数所表示的类或接口是否相同,或是否是其超类或超接口
if (clazz.isAssignableFrom(allClass.get(i))) {
if (!clazz.equals(allClass.get(i))) {
// 自身并不加进去
list.add(allClass.get(i));
}
}
}
} catch (Exception e) {
throw new RuntimeException("出现异常" + e.getMessage());
}
}
return list;
}
/**
* 从一个指定路径下查找所有的类
*
* @param packagename
*/
private static ArrayList<Class> getAllClass(String packagename) {
List<String> classNameList = getClassName(packagename);
ArrayList<Class> list = new ArrayList<>();
for (String className : classNameList) {
try {
String realClassName = className.replace("/", ".");
list.add(Class.forName(realClassName));
} catch (ClassNotFoundException e) {
throw new RuntimeException("load class from name failed:" + className + e.getMessage());
}
}
return list;
}
/**
* 获取某包下所有类
*
* @param packageName 包名
* @return 类的完整名称
*/
public static List<String> getClassName(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 = getClassNameByFile(fileSearchPath);
} else if (type.equals("jar")) {
try {
JarURLConnection
jarURLConnection = (JarURLConnection) url.openConnection();
JarFile jarFile = jarURLConnection.getJarFile();
fileNames = getClassNameByJar(jarFile, packagePath);
} catch (java.io.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> getClassNameByFile(String filePath) {
List<String> myClassName = new ArrayList<String>();
File file = new File(filePath);
File[] childFiles = file.listFiles();
for (File childFile : childFiles) {
if (childFile.isDirectory()) {
myClassName.addAll(getClassNameByFile(childFile.getPath()));
} else {
String childFilePath = childFile.getPath();
if (childFilePath.endsWith(".class")) {
childFilePath = childFilePath.substring(childFilePath.indexOf("/classes") + 9, childFilePath.lastIndexOf("."));
childFilePath = childFilePath.replace("/", ".");
myClassName.add(childFilePath);
}
}
}
return myClassName;
}
/**
* 从jar获取某包下所有类
*
* @return 类的完整名称
*/
private static List<String> getClassNameByJar(JarFile jarFile, String packagePath) {
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")) {
entryName =
entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));
myClassName.add(entryName);
}
}
} catch (Exception e) {
throw new RuntimeException("发生异常:" + e.getMessage());
}
return myClassName;
}
private static LoadingCache<String, ArrayList<Class>> buildAllClassCache() {
LoadingCache<String, ArrayList<Class>> cache = CacheBuilder.newBuilder()
//设置并发级别为8,并发级别是指可以同时写缓存的线程数
.concurrencyLevel(8)
//设置缓存容器的初始容量为10
.initialCapacity(10)
//设置缓存最大容量为100,超过100之后就会按照LRU最近虽少使用算法来移除缓存项
.maximumSize(100)
//设置写缓存后n秒钟过期
.expireAfterWrite(30, TimeUnit.DAYS)
//build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存
.build(new AllClassCacheLoader());
return cache;
}
/**
* 从diamond获取配置并加载到缓存
*/
public static class AllClassCacheLoader extends CacheLoader<String, ArrayList<Class>> {
@Override
public ArrayList<Class> load(String packagename) throws Exception {
return getAllClass(packagename);
}
}
}
网友评论