首页 > 编程语言 >java代码重构 接口和接口实现类合并

java代码重构 接口和接口实现类合并

时间:2024-11-04 15:46:59浏览次数:3  
标签:重构 java String 接口 File directory import com append

maven

<dependency>
            <groupId>com.github.javaparser</groupId>
            <artifactId>javaparser-core</artifactId>
            <version>3.24.0</version>
        </dependency>

代码

package com.xx;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.type.Type;
import com.shocksoft.component.util.JacksonUtil;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 接口-接口实现 合并
 */
public class ScanMain {


    private static MethodDeclaration findMatchingMethod(ClassOrInterfaceDeclaration implementationClass, String methodName, List<Type> paramTypes) {
        for (MethodDeclaration method : implementationClass.getMethods()) {
            if (method.getNameAsString().equals(methodName) && haveSameParameters(method, paramTypes)) {
                return method;
            }
        }
        return null;
    }

    private static boolean haveSameParameters(MethodDeclaration method, List<Type> paramTypes) {
        List<Type> methodParamTypes = method.getParameters().stream()
                .map(Parameter::getType)
                .collect(Collectors.toList());
        return methodParamTypes.containsAll(paramTypes) && paramTypes.containsAll(methodParamTypes);
    }

    private static void dd(MData mData) throws Exception {
        // 读取源代码文件
        JavaParser javaParser = new JavaParser();
        String api = mData.getApiFile();
        String apiImpl = mData.getApiImplFile();
        CompilationUnit apiUnit = javaParser.parse(new File(api)).getResult().get();
        CompilationUnit apiImplUnit = javaParser.parse(new File(apiImpl)).getResult().get();
        String apiClassName = mData.getApiClassName();
        String apiImplClassName = mData.getApiImplClassName();
        ClassOrInterfaceDeclaration apiClass = apiUnit.getInterfaceByName(apiClassName).orElse(null);
        ClassOrInterfaceDeclaration apiImplClass = apiImplUnit.getClassByName(apiImplClassName).orElse(null);

        assert apiClass != null;
        assert apiImplClass != null;

        StringBuilder src = new StringBuilder();

        src.append(apiUnit.getPackageDeclaration().get()).append("\n");

        Set<String> importPackage = new LinkedHashSet<>();
        NodeList<ImportDeclaration> apiPack = apiUnit.getImports();
        NodeList<ImportDeclaration> apiImplPack = apiImplUnit.getImports();
        for (ImportDeclaration declaration : apiPack) {
            importPackage.add(declaration.toString());
        }
        for (ImportDeclaration declaration : apiImplPack) {
            importPackage.add(declaration.toString());
        }
        for (String s : importPackage) {
            src.append(s.replace("\n", "")).append("\n");
        }
        Set<String> importAn = new LinkedHashSet<>();
        NodeList<AnnotationExpr> apiAn = apiClass.getAnnotations();
        for (AnnotationExpr annotation : apiAn) {
            importAn.add(annotation.toString());
        }
        NodeList<AnnotationExpr> apiImplAn = apiImplClass.getAnnotations();
        for (AnnotationExpr annotation : apiImplAn) {
            importAn.add(annotation.toString());
        }

        for (String s : importAn) {
            src.append(s).append("\n");
        }

        src.append("public class " + apiClassName + " {").append("\n");

        List<FieldDeclaration> fields = apiImplClass.getFields();
        for (FieldDeclaration field : fields) {
            src.append(field.toString()).append("\n");
        }

        Map<String, String> methodImplementationMap = new LinkedHashMap<>();
        List<MethodDeclaration> interfaceMethods = apiClass.getMethods();
        for (MethodDeclaration interfaceMethod : interfaceMethods) {
            String interfaceMethodName = interfaceMethod.getNameAsString();
            List<Type> interfaceMethodParamTypes = interfaceMethod.getParameters().stream()
                    .map(Parameter::getType)
                    .collect(Collectors.toList());

            MethodDeclaration implementedMethod = findMatchingMethod(apiImplClass, interfaceMethodName, interfaceMethodParamTypes);
            if (implementedMethod != null) {
                methodImplementationMap.put(interfaceMethod.toString(), implementedMethod.getBody().get().toString());
            }
        }

        for (Map.Entry<String, String> entry : methodImplementationMap.entrySet()) {
            src.append(entry.getKey().replace(";", "")).append("\n");
            src.append(entry.getValue()).append("\n");
        }
        src.append("}");

//        System.out.println(src);

        FileUtil.writeUtf8String(src.toString(), api);
        FileUtil.del(apiImpl);

    }

    @Data
    public static class MData {
        private String apiImplFile;
        private String apiFile;
        private String apiClassName;
        private String apiImplClassName;
    }

    public static List<MData> scan() {
        List<String> list = scanClassesWithAnnotation("com.xx", RestController.class);
        List<MData> mm = new ArrayList<>();
        for (String s : list) {
            if (StrUtil.contains(s, "ApiImpl")) {
                String impl = StrUtil.replace(s, "\\target\\classes", "\\src\\main\\java");
                impl = StrUtil.replace(impl, ".class", ".java");
                String api = StrUtil.replace(impl, "\\impl", "");
                api = StrUtil.replace(api, "Impl", "");
                if (new File(api).exists()) {
                    MData e = new MData();
                    e.setApiImplFile(impl);
                    e.setApiFile(api);
                    e.setApiClassName(FileUtil.getName(api).replace(".java", ""));
                    e.setApiImplClassName(FileUtil.getName(impl).replace(".java", ""));
                    mm.add(e);
                } else {
                    System.out.println(api);
                }
            }
        }
        return mm;
    }


    public static void main(String[] args) throws Exception {
        // dd();
        List<MData> data = scan();
        System.out.println("检测到需要优化的项目 " + data.size());
        int i = 1;
        for (MData mData : data) {
            System.out.println("正在处理 " + i++);
            dd(mData);
        }
        cleanEmptyDir();
        System.out.println("ok");
    }

    public static List<String> scanClassesWithAnnotation(String packageName, Class<?> annotationClass) {
        List<String> classes = new ArrayList<>();
        String packagePath = packageName.replace('.', '/');
        URL resource = Thread.currentThread().getContextClassLoader().getResource(packagePath);
        if (resource != null) {
            File directory = new File(resource.getFile());
            if (directory.exists() && directory.isDirectory()) {
                scanDirectory(directory, packageName, annotationClass, classes);
            }
        }
        return classes;
    }

    private static void scanDirectory(File directory, String packageName, Class<?> annotationClass, List<String> classes) {
        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    String subPackageName = packageName + "." + file.getName();
                    scanDirectory(file, subPackageName, annotationClass, classes);
                } else if (file.getName().endsWith(".class")) {
                    String className = packageName + "." + file.getName().substring(0, file.getName().length() - 6);
                    try {
                        Class<?> clazz = Class.forName(className);
                        if (clazz.isAnnotationPresent((Class<? extends Annotation>) annotationClass)) {
                            classes.add(file.getAbsolutePath());
                        }
                        if (clazz.isAnnotationPresent(RestController.class)
                                && !clazz.isAnnotationPresent(Tag.class)
                        ) {
                            System.out.println(className);
                        }

                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

     public static void cleanEmptyDir() {
        // 替换为你想要清理的目录路径
        File directory = new File("D:\\workspace\\xxx\\src\\main\\java\\com\\xx");
        deleteEmptyDirectories(directory);
    }

    /**
     * 删除所有空目录
     *
     * @param directory 要清理的目录
     */
    public static void deleteEmptyDirectories(File directory) {
        if (directory.exists() && directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        deleteEmptyDirectories(file);
                    }
                }
            }
            // 再次检查目录是否为空,如果是,则删除
            if (directory.listFiles().length == 0) {
                directory.delete();
                System.out.println("Deleted empty directory: " + directory.getAbsolutePath());
            }
        }
    }
}

标签:重构,java,String,接口,File,directory,import,com,append
From: https://www.cnblogs.com/ranger-dev/p/18525430

相关文章

  • 现在的Java面试都会问哪些问题?
    前言金九银十已过,不少人找LZ咨询,问我现在的面试需要提前准备什么?为了造福更多的开发者,也为了让更多的小伙伴通过面试;LZ近期也一直想着怎么才能帮到大家。所以近期在各大渠道整合大厂相关面试题,并结合了我一位现在已经入职阿里(阿里的Offer就是他今年的第15张offer)的朋友一整年......
  • 接口自动化测试思路和实战(5):【推荐】混合测试自动化框架(关键字+数据驱动)
    混合测试自动化框架(关键字+数据驱动)关键字驱动或表驱动的测试框架这个框架需要开发数据表和关键字。这些数据表和关键字独立于执行它们的测试自动化工具,并可以用来“驱动"待测应用程序和数据的测试脚本代码,关键字驱动测试看上去与手工测试用例很类似。在一个关键字驱动测试......
  • Java面试高频问题:深入理解 volatile 关键字的作用与实际应用
    在Java并发编程中,volatile是一个常见的关键字,尤其在多线程面试中经常被提及。很多开发者只了解volatile能“防止指令重排序”或者“保证可见性”,但真正理解其应用并正确使用的人并不多。这篇文章将详细介绍volatile的原理、使用场景、实际案例和面试常见问题,帮助你更......
  • 深入理解Java中的数组克隆:浅克隆与深克隆
    深入理解Java中的数组克隆:浅克隆与深克隆在Java编程中,数组的克隆是一个常见的需求,尤其是在处理复杂数据结构时。Java提供了数组的clone方法,但这个方法的行为在不同情况下有所不同。本文将通过一个具体的代码示例,深入探讨Java中数组的浅克隆和深克隆的概念,并解释它们之间的区别......
  • 【Postman深入测试接口的详细指南】保姆级
    Postman深入测试接口的详细操作步骤一、创建测试集合二、使用环境变量三、编写请求四、编写测试脚本五、数据驱动测试六、模拟请求(Mocking)1.创建MockServer2.定义响应3.使用MockServer进行请求七、API监控1.创建监控2.运行监控一、创建测试集合打开Postman......
  • 说说Java的类加载机制?究竟什么是双亲委派模型?6B
    首先引入一个概念,什么是Java类加载器?一句话总结:类加载器(classloader)用来加载Java类到Java虚拟机中。官方总结:Java类加载器(英语:JavaClassloader)是Java运行时环境(JavaRuntimeEnvironment)的一部分,负责动态加载Java类到Java虚拟机的内存空间中。类通常是按需加载,即第一次使......
  • 【JAVA】Java基础—Java概述:Java语言的历史与发展
    Java是一种广泛使用的编程语言,因其跨平台性、面向对象特性和强大的生态系统而受到开发者的青睐。Java最初由SunMicrosystems于1995年发布,经过多年的发展,已成为企业级应用、移动应用、Web开发和大数据处理等领域的主流语言。企业级应用:Java在大型企业应用中占据主导地位,特别......
  • 【JAVA】Java基础—Java概述:Java的特点
    Java语言因其独特的设计理念和强大的功能,在软件开发领域获得了广泛的应用。以下是Java的几个主要特点的详细说明,以及通俗易懂的例子来帮助理解这些概念。1.跨平台性理论说明Java的跨平台性是其最显著的特点之一,得益于Java虚拟机(JVM)的设计。Java程序在编译后生成字节码(.clas......
  • clean-code-javascript系列之并发
    使用Promises,不要使用回调回调不够简洁,因为他们会产生过多的嵌套。在ES2015/ES6中,Promises已经是内置的全局类型了,使用它们吧!不好的:require('request').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin',(requestErr,response)=>{if(requestErr......
  • 7.2、实验二:被动接口和单播更新
    源文件链接:7.2、实验二:被动接口和单播更新:https://url02.ctfile.com/d/61945102-63671890-6af6ec?p=2707(访问密码:2707)一、被动接口1.介绍定义:在路由协议的配置中,一个被动接口指的是一个接口不发送路由更新包的配置方式,但仍然可以接收和处理传入的路由更新。作用:......