类扫描

作者: 知止9528 | 来源:发表于2021-07-24 11:12 被阅读0次
    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);
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:类扫描

          本文链接:https://www.haomeiwen.com/subject/iugmmltx.html