美文网首页
java获取类的依赖关系:javassist扫描类的依赖

java获取类的依赖关系:javassist扫描类的依赖

作者: 夜月河色 | 来源:发表于2020-02-13 00:55 被阅读0次
    import javassist.ClassClassPath;
    import javassist.ClassPool;
    import javassist.CtClass;
    import javassist.NotFoundException;
    import javassist.bytecode.AnnotationsAttribute;
    import javassist.bytecode.ClassFile;
    import javassist.bytecode.FieldInfo;
    import javassist.bytecode.MethodInfo;
    import javassist.bytecode.annotation.Annotation;
    
    import java.util.List;
    import java.util.Set;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * 通过javassist库获取类的依赖
     * @author tgj Administrator
     */
    public class ClassRelyByJavassistUtil {
    
        //获取类注解
        public static Set<String> getClassAnnotations(String classPath, Set<String> set) throws NotFoundException {
            CtClass ctClass=getCtClass(classPath);
            ClassFile classFile=ctClass.getClassFile();
    
            AnnotationsAttribute attribute = (AnnotationsAttribute) classFile.getAttribute(AnnotationsAttribute.visibleTag);
            Annotation[] annotations=attribute.getAnnotations();
            for (Annotation annotation:annotations){
                set.add(annotation.getTypeName());
            }
    
            ctClass.detach();//删除缓存
    
            return set;
        }
    
        //获取父类
        public static Set<String> getSuperClass(String classPath, Set<String> set) throws NotFoundException {
            CtClass ctClass=getCtClass(classPath);
            ClassFile classFile=ctClass.getClassFile();
    
            String superClass = classFile.getSuperclass();
            if (!"".equals(superClass) && superClass != null && !set.contains(superClass)) {
                set.add(superClass);
            }
    
            ctClass.detach();//删除缓存
    
            return set;
        }
    
        //获取接口
        public static Set<String> getInterface(String classPath, Set<String> set) throws NotFoundException {
            CtClass ctClass=getCtClass(classPath);
            ClassFile classFile=ctClass.getClassFile();
    
            String[] interfaces = classFile.getInterfaces();
            if (interfaces != null) {
                for (String face : interfaces) {
                    String className = getClassName(face);
                    addClassName(set, className);
                }
            }
    
            ctClass.detach();//删除缓存
    
            return set;
        }
    
        //获取字段类型
        public static Set<String> getFieldsType(String classPath, Set<String> set) throws NotFoundException {
            CtClass ctClass=getCtClass(classPath);
            ClassFile classFile=ctClass.getClassFile();
    
            List<FieldInfo> fieldInfoList = classFile.getFields();
            if (fieldInfoList != null) {
                for (FieldInfo fieldInfo : fieldInfoList) {
                    String descriptor = fieldInfo.getDescriptor();
                    if (descriptor.startsWith("L") && descriptor.endsWith(";")) {
                        String className = descriptor.substring(1, descriptor.length() - 1);
                        className = getClassName(className);
                        addClassName(set, className);
                    }
    
                    if (descriptor.startsWith("[L") && descriptor.endsWith(";")) {
                        String className = descriptor.substring(2, descriptor.length() - 1);
                        className = getClassName(className);
                        addClassName(set, className);
                    }
                }
            }
    
            ctClass.detach();//删除缓存
    
            return set;
        }
    
        //遍历代码内使用的类,包含方法实现里使用的类,不包含方法签名里的类
        public static Set<String> getClassRelyClass(String classPath, Set<String> set) throws NotFoundException {
            CtClass ctClass=getCtClass(classPath);
            ClassFile classFile=ctClass.getClassFile();
    
            Set<String> classNames=classFile.getConstPool().getClassNames();
            for (String className : classNames) {
                if (className.startsWith("[L")) {
                    className = className.substring(2, className.length() - 1);
                } else if (className.startsWith("[")) {
                    continue;
                }
                className = getClassName(className);
                addClassName(set, className);
            }
    
            ctClass.detach();//删除缓存
    
            return set;
        }
    
        //获取方法声明的参数和返回值包含的所有类
        public static Set<String> getMethodSignatureClass(String classPath,String methodName, Set<String> set) throws NotFoundException {
            CtClass ctClass=getCtClass(classPath);
            ClassFile classFile=ctClass.getClassFile();
    
            MethodInfo methodInfo = classFile.getMethod(methodName);
            String descriptor = methodInfo.getDescriptor();
            extractClassNames(descriptor, set);
    
            ctClass.detach();//删除缓存
    
            return set;
        }
    
        //获取默认的ClassPool
        public static CtClass getCtClass(String classPath) throws NotFoundException {
            try {
                ClassPool classPool = new ClassPool(true);
                classPool.insertClassPath(new ClassClassPath(Class.forName(classPath)));//为防止项目被打成jar包,请使用该语句
                return classPool.getCtClass(classPath);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        //过滤类名
        private static void extractClassNames(String descriptor, Set<String> set) {
            String reg = "(L.+?;)";
            Pattern pattern = Pattern.compile(reg);
            Matcher matcher = pattern.matcher(descriptor);
            while (matcher.find()) {
                String className = matcher.group();
                className = className.substring(1, className.length() - 1);
                className = getClassName(className);
                addClassName(set, className);
            }
        }
    
        // 如果当前节点已经被访问过,不再将它添加到当前类的直接依赖中
        private static void addClassName(Set<String> set, String className) {
            if (!set.contains(className)) {
                set.add(className);
            }
        }
    
        //路径替换
        private static String getClassName(String className) {
            return className.replaceAll("/", ".");
        }
    }
    

    相关文章

      网友评论

          本文标题:java获取类的依赖关系:javassist扫描类的依赖

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