扫描Class文件,获取所有可调用方法及方法的入参等信息

主要思路:
1.从gitlab上下载contract源码,使用org.eclipse.jgit
2.mvn编译并把生成的jar和依赖的jar拷贝到指定目录下,使用org.apache.maven.shared maven-invoker
3.扫描源码列出所有以I开头,以.java结尾的文件绝对路径getCanonicalPath()
4.根据第三步的文件绝对路径,切割转换出className,package+文件名
5.Class获取Method,解析每个method,java基本类型需要转换为class类的名称

MethodEntity.java

public class MethodEntity {
    // 接口类名,例如:IZZHaHaService
    private String interfaceClassName;
    // 接口类名,包含package信息,例如:com.bj58.zhuanzhuan.IZZHaHaService
    private String interfaceClassFullName;
    private String methodName;
    // 入参类型的完整名称,按照入参顺序排列,例如:java.util.List<com.bj58.zhuanzhuan.entity.ViViEntity>
    private List<String> paramterTypeCanonicalNames;
    // 入参类型名称,按照入参顺序排列,例如:List
    private List<String> paramterTypeNames;

    /**
     * 根据函数名和入参的类型及名称,判断当前实例是否是要找的
     * 
     * @param methodName
     *            不为空
     * @param paramNames
     *            参数类型列表
     * @param interfaceName
     *            接口类名,传null不做比对
     * @return True or False
     */
    public Boolean isSeached(String methodName, List<String> paramNames, String interfaceName) {
        if (interfaceName != null) {
            if (!interfaceName.equals(this.interfaceClassName)) {
                return Boolean.FALSE;
            }
        }

        if (methodName == null) {
            return Boolean.FALSE;
        }
        if (paramNames == null && getParamterTypeNames() == null) {
            return Boolean.TRUE;
        }

        if ((paramNames == null && getParamterTypeNames() != null)
                || paramNames != null && getParamterTypeNames() == null
                || paramNames.size() != getParamterTypeNames().size()) {
            return Boolean.FALSE;
        }

        if (methodName.equals(getMethodName())) {
            return paramNames.equals(getParamterTypeNames());
        } else {
            return Boolean.FALSE;
        }
    }
    public String getInterfaceClassFullName() {
        return interfaceClassFullName;
    }

    public void setInterfaceClassFullName(String interfaceClassFullName) {
        this.interfaceClassFullName = interfaceClassFullName;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public List<String> getParamterTypeCanonicalNames() {
        return paramterTypeCanonicalNames;
    }

    public void setParamterTypeCanonicalNames(List<String> paramterTypeCanonicalNames) {
        this.paramterTypeCanonicalNames = paramterTypeCanonicalNames;
    }

    public List<String> getParamterTypeNames() {
        return paramterTypeNames;
    }

    public void setParamterTypeNames(List<String> paramterTypeNames) {
        this.paramterTypeNames = paramterTypeNames;
    }

    public String getInterfaceClassName() {
        return interfaceClassName;
    }

    public void setInterfaceClassName(String interfaceClassName) {
        this.interfaceClassName = interfaceClassName;
    }

}

扫包,获取所有的可调用方法

// java基本数据类型和对应的类
private static Map<String, String> basicDataTypeReference = new HashMap<String, String>() {
        private static final long serialVersionUID = 4477784757087366211L;
        {
            // 九种基本类型
            // java.lang.Boolean
            // java.lang.Character
            // java.lang.Byte
            // java.lang.Short
            // java.lang.Integer
            // java.lang.Long
            // java.lang.Float
            // java.lang.Double
            // java.lang.Void
            put("boolean", "java.lang.Boolean");
            put("char", "java.lang.Character");
            put("byte", "java.lang.Byte");
            put("short", "java.lang.Short");
            put("int", "java.lang.Integer");
            put("long", "java.lang.Long");
            put("float", "java.lang.Float");
            put("double", "java.lang.Double");
        }
    };

/**
* 扫码contract目录下的所有接口文件
* 
* @param serviceName
*            服务名,例如zzpost
* @throws Exception
*/
public void scanContractFiles(String serviceName) throws Exception {
    // 拿到所有以.java结尾的文件
    Collection<File> sourceFiles = FileUtils.listFiles(file, new WildcardFileFilter("I*.java"),TrueFileFilter.INSTANCE);
    for (File f : sourceFiles) {
        String canonicalPath = f.getCanonicalPath();
        String fileName = f.getName();
                // D:\aaa\com\bj58\zhuanzhuan\IHaHaService.java
                // 以com开始不要最后的.java com.bj58.zhuanzhuan.IHaHaService
        String clazzPath = canonicalPath.substring(canonicalPath.indexOf("com"), canonicalPath.length() - 5)
                        .replace("\\", ".").replace("/", ".");

        Class<?> clazz = Class.forName(clazzPath, true, loader);
        for (Method m : clazz.getMethods()) {
            MethodEntity entity = new MethodEntity();
            List<String> paramTypeCanonicalNames = new ArrayList<>();
            List<String> paramTypeNames = new ArrayList<>();

            // 5 为".java"的长度
            entity.setInterfaceClassName(fileName.substring(0, fileName.length() - 5));
            entity.setInterfaceClassFullName(clazzPath);
            entity.setMethodName(m.getName());

            for (Parameter p : m.getParameters()) {
                String paramSimpleName = p.getType().getSimpleName();
                // List,抹掉具体类型
                paramTypeNames.add(basicDataType2ClassType(paramSimpleName, true));

                String paramClassName = p.getParameterizedType().getTypeName();
                // java.util.List<java.lang.Long>,参数类型的完整名称
                paramTypeCanonicalNames.add(basicDataType2ClassType(paramClassName, false));
            }

            entity.setParamterTypeCanonicalNames(paramTypeCanonicalNames);
            entity.setParamterTypeNames(paramTypeNames);
            methodEntities.add(entity);

            String json = JSON.toJSONString(entity);
            System.out.println(json);
        }
    }
}
 /**
     * 基本数据类型替换为基本类型对应的class类
     * 
     * @param type
     *            需要转换的类型
     * @param isSimpleName
     *            是否为类名简写
     * @return String
     */
private String basicDataType2ClassType(String type, Boolean isSimpleName) {
    String res = "";
    if (basicDataTypeReference.containsKey(type)) {
        res = basicDataTypeReference.get(type);
        if (isSimpleName) {
            res = res.substring(res.lastIndexOf(".") + 1);
        }
        return res;
     } else {
        return type;
     }
}

console输出如下:


{"interfaceClassFullName":"com.bj58.zhuanzhuan.IAaaaService","interfaceClassName":"IAaaaService","methodName":"getInfo","paramterTypeCanonicalNames":["java.lang.String","java.util.List<java.lang.Long>"],"paramterTypeNames":["String","List"]}
{"interfaceClassFullName":"com.bj58.zhuanzhuan.IBiuBiuService","interfaceClassName":"IBiuBiuService","methodName":"getUser","paramterTypeCanonicalNames":["java.lang.String","java.lang.String","java.lang.String","java.lang.Integer","java.lang.Integer"],"paramterTypeNames":["String","String","String","Integer","Integer"]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章