美文网首页
模块依赖分析

模块依赖分析

作者: 蓝笔头 | 来源:发表于2021-09-08 09:51 被阅读0次

1. 递归打印某个模块的所有类文件

public class ModuleDependencyAnalyser {

    public static void main(String[] args) {
        ModuleDependencyAnalyser analyser = new ModuleDependencyAnalyser();
        File file = new File("xxx");
        analyser.printClass(file, 0);
    }

    public void printClass(File file, int indent) {
        printIndent(indent);
        System.out.println(file.getName());
        if (file.isDirectory()) {
            for (File subFile : file.listFiles()) {
                printClass(subFile, indent + 1);
            }
        }
    }

    public void printIndent(int indent) {
        for (int i = 0; i < indent; ++ i) {
            System.out.print("----");
        }
    }
}

2. 获取某个模块的所有类的全路径名

@UtilityClass
public class ClassUtils {
    public static List<String> getAllClassesFullName(String path) {
        List<File> javaFiles = getAllJavaFiles(path);
        return javaFiles.stream()
            .map(file -> convertToClassFullName(file, path))
            .collect(Collectors.toList());
    }

    public static List<File> getAllJavaFiles(String path) {
        File file = new File(path);
        List<File> javaFiles = new ArrayList<>();
        collectAllJavaFiles(file, javaFiles);
        return javaFiles;
    }

    private static void collectAllJavaFiles(File file, List<File> javaFiles) {
        if (file.isDirectory()) {
            for (File subFile : file.listFiles()) {
                collectAllJavaFiles(subFile, javaFiles);
            }
        }
        if (file.getName().endsWith(".java")) {
            javaFiles.add(file);
        }
    }

    public static String convertToClassFullName(File file, String path) {
        return Optional.of(file)
            .map(File::getAbsolutePath)
            .map(v -> v.substring(path.length() + 1)) // 截取项目路径
            .map(v -> v.replaceAll("\\\\", "\\.")) // 文件路径分隔符 \ 转换为 Java 包分隔符 .
            .map(v -> v.substring(0, v.length() - 5)) // 去掉 .java 后缀
            .orElse(null);
    }
}

测试类:

@Slf4j
public class ModuleDependencyAnalyser {

    public static void main(String[] args) {
        String path = "F:\\work\\project\\AthenaWeb\\athena-learning\\src\\main\\java";
        List<String> classes = ClassUtils.getAllClassesFullName(path);
        log.info("classes count: {}", classes.size());
    }
}

3. 模块依赖分析

(1)获取每一个 Java 源代码文件中所有的 import 类。

@UtilityClass
public class ImportUtils {
    @SneakyThrows
    public static List<String> getAllImportClasses(File file) {
        List<String> importClasses = new ArrayList<>();
        List<String> lines = IOUtils.readLines(new FileInputStream(file));
        for (String line : lines) {
            if (line.startsWith("import")) {
                String[] parts = line.split(" "); // 通过 " " 字符分割 import 行
                String lastPart = parts[parts.length - 1]; // 得到包含 ; 的类命令
                String importClass = lastPart.substring(0, lastPart.length() - 1); // 去掉结尾的 ; 符号

                importClasses.add(importClass);
            }
        }
        return importClasses;
    }
}

(2)定义保存依赖关系的数据结构

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DependencyData {
    @JsonProperty("athena_web_class")
    private String athenaWebClass;

    @JsonProperty("learning_dependency")
    private List<String> learningDependency;

    @JsonProperty("learning_data_access_dependency")
    private List<String> learningDataAccessDependency;

    @JsonProperty("learning_dependency_count")
    public int getLearningDependencyCount() {
        return this.learningDependency.size();
    }

    @JsonProperty("learning_data_access_dependency_count")
    public int getLearningDataAccessDependencyCount() {
        return this.learningDataAccessDependency.size();
    }

    @JsonIgnore
    public int getDependencyCount() {
        return getLearningDependencyCount() + getLearningDataAccessDependencyCount();
    }

    public static DependencyData of(String athenaWebClass, List<String> learningDependency, List<String> learningDataAccessDependency) {
        return DependencyData.builder()
            .athenaWebClass(athenaWebClass)
            .learningDependency(learningDependency)
            .learningDataAccessDependency(learningDataAccessDependency)
            .build();
    }
}

(3)分析模块依赖

@Slf4j
public class ModuleDependencyAnalyser {
    private static final String LEARNING_PATH = "F:\\work\\project\\AthenaWeb\\athena-learning\\src\\main\\java";
    private static final String LEARNING_DATA_ACCESS_PATH = "F:\\work\\project\\AthenaWeb\\athena-data-access\\src\\main\\java";
    private static final String ATHENA_WEB_PATH = "F:\\work\\project\\AthenaWeb\\athena-web\\src\\main\\java";

    public static void main(String[] args) {
        List<String> learningClasses = ClassUtils.getAllClassesFullName(LEARNING_PATH);
        log.info("learningClasses count: {}", learningClasses.size());
        List<String> learningDataAccessClasses = ClassUtils.getAllClassesFullName(LEARNING_DATA_ACCESS_PATH);
        log.info("learningDataAccessClasses count: {}", learningDataAccessClasses.size());


        List<DependencyData> dependencyDatas = new ArrayList<>();

        List<File> allJavaFiles = ClassUtils.getAllJavaFiles(ATHENA_WEB_PATH);
        for (File file : allJavaFiles) {
            List<String> importClasses = ImportUtils.getAllImportClasses(file);

            String athenaWebClass = ClassUtils.convertToClassFullName(file, ATHENA_WEB_PATH);

            // 求 importClasses 和 learningClasses 的交集
            List<String> learningDependency = ListUtils.retainAll(importClasses, learningClasses);
            // 求 importClasses 和 learningDataAccessClasses 的交集
            List<String> learningDataAccessDependency = ListUtils.retainAll(importClasses, learningDataAccessClasses);
            // ListUtils 全路径:org.apache.commons.collections4.ListUtils

            DependencyData dependencyData = DependencyData.of(athenaWebClass, learningDependency, learningDataAccessDependency);
            if (dependencyData.getDependencyCount() > 0) {
                dependencyDatas.add(dependencyData);
            }
        }

        // 按照依赖数量降序排序
        Collections.sort(dependencyDatas, Comparator.comparingInt(DependencyData::getDependencyCount).reversed());
        String json = JsonUtils.serialize(dependencyDatas);
        System.out.println(json);
    }
}

JsonUtils 的实现参考:Jackson 格式化输出

相关文章

  • 模块依赖分析

    1. 递归打印某个模块的所有类文件 2. 获取某个模块的所有类的全路径名 测试类: 3. 模块依赖分析 (1)获取...

  • ⽆包构建

    Webpack、Rollup 等都是基于⼀个或多个⼊⼝点模块,通过依赖分析将有依赖关系的模块打包到⼀起,最后形成少...

  • webpack

    webpack是啥? 静态模块打包工具。 会从入口文件开始,递归的分析模块以及依赖模块,然后进行模块路径解析,lo...

  • 前端自动化工具学习--webpack经典7分钟入门

    一.什么是 WebpackWebpack 是一个模块打包器。它将根据模块的依赖关系进行静态分析,然后将这些模块按照...

  • webpack入门教学

    一.什么是 Webpack Webpack 是一个模块打包器。它将根据模块的依赖关系进行静态分析,然后将这些模块按...

  • webpack 先这么用

    webpack 介绍Webpack 是一个模块打包器。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的...

  • Angular.js

    强推! angular 模块依赖分析 可视化哦 Create graphs of your angular pro...

  • 初识webpack

    webpack初识 webpack是什么? 前端资源加载/打包工具。根据模块的依赖关系进行静态分析,将模块按照指定...

  • Webpack介绍

    什么是Webpack webpack是一个模块打包器。它根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规...

  • python大数据挖掘系列之基础知识入门(numpy、panda

    数据分析的模块有哪些: numpy 高效处理数据,提供数组支持,很多模块都依赖它,比如pandas,scipy,m...

网友评论

      本文标题:模块依赖分析

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