代码手术刀-自定义你的代码重构工具
前言
笔者近日在做代码仓库的存量代码缩减工作,首先考虑的是基于静态扫描的缩减,尝试使用了很多工具来对代码进行优化,例如PMD、IDEA自带的inspect功能、findBugs等。但是无一例外,要么过于“保守”,只给出扫描结果,但是无法实现一键优化,要么直接就是有bug(这里特指IDEA2023.1.5专业版-inspect功能扫描problems清单里的unused declaration)。对于懒人而言,挨个手动点击几百次按钮和坐牢无异,遂自己写了一个工具对大部分已明确的优化点进行一键修改(具体是使用lombok的@Data注解替换显式的getter/setter以及toString方法)。
本文内容主要分为三个部分,第一部分详细讲述工具实现的思路,第二部分会对用到的开源工具javaParser进行简要的介绍,第三部分提供了工具细致的使用说明。
实现思路
在翻阅历史代码时,发现不少工程仓库里很多类依然是用的IDE生成的getter/setter,如果使用Lombok的@Data注解替换,可以带来几个优点。
回过头来看,如果我们要写一个工具,对整个代码工程所有类进行全量扫描,并且使用lombok来替换其中的“没有特殊逻辑”的getter和setter,需要哪些步骤。
下面对每个步骤的实现进行说明。
工程扫描
工程扫描比较简单,给一个工程路径,然后递归调用,过滤出所有的.java文件即可。
private static List<File> scanJavaFiles(File file) { List<File> result = Lists.newArrayList(); if (file.isDirectory()) { File[] files = file.listFiles(); if (files == null) { return result; } for (File f : files) { result.addAll(scanJavaFiles(f)); } } if (file.getName().endsWith(".java")) { result.add(file); } return result; }
使用注解替换getter/setter
在拿到所有文件的列表之后,需要对其进行处理。
这里使用github上开源的工具javaParser来对类进行解析、代码提取、删除以及内容新增,javaParser会在下一章节进行介绍。
这里简单粗暴了一些,直接使用equals判断方法体,其实javaParser提供了更完善的api来分析语义。
更新java文件
在完成对代码的清理之后,需要将内容更新到java文件,CompilationUnit重写了toString方法,可以支持直接将代码转换成字符串的形式。
JavaParser介绍
JavaParser是什么?
JavaParser 是一个开源的 Java 源代码分析工具,它提供了一系列简单的API来解析、修改和生成 Java 代码。
举个例子,我们可以使用javaparser轻松的实现下面几个操作:
在上一章节里就用到了数据提取,源码替换功能。这里附上JavaParser的相关链接:
官网: https://javaparser.org/ github: https://github.com/javaparser/javaparser wiki: https://github.com/javaparser/javaparser.wiki.git javadoc: https://www.javadoc.io/doc/com.github.javaparser/javaparser-core/latest/index.html
核心组件
JavaParser 的主要构成由以下几个组件组成:
通常不需要咱们显式调用,JavaParser将具体的细节实现隐藏在内部,调用方只需要使用开放api即可完成源码到AST的转换。具体可以翻阅com.github.javaparser.GeneratedJavaParser
2. Parser(语法解析器):语法分析器接收词法分析器生成的tokens,并根据Java语言的语法规则将它们组合成各种语法结构,如表达式、语句、类定义等。这个过程构建出一个抽象语法树(AST)。
com.github.javaparser.JavaParser
这是最常用的类,用于触发解析过程并生成AST,在上一章节中,使用StaticJavaParser将源文件解析成CompilationUnit,在parse方法的内部使用了JavaParser完成这一解析过程。
3. AST(抽象语法树):AST 是 JavaParser 的核心数据结构,它以层次化的方式表示了源代码的结构。AST 由一系列的节点组成,每个节点表示源代码中的一个元素,如类、方法、字段、表达式等。每个节点都包含有关该元素的信息,例如名称、类型、修饰符等。
AST是后续操作(如遍历、分析、修改)的基础,也是使用方操作最频繁的类。上一章节使用的com.github.javaparser.ast.CompilationUnit
是一个非常重要的类,它代表了Java源代码文件的根节点,是这个结构的抽象表示,包含整个文件的结构,例如:
通过操作CompilationUnit提供的公有方法,可以访问和修改文件中的元素。包括:
4. Visitors(访问器):顾名思义,这是一个采用访问者模式设计的组件,可以用于遍历和操作 AST 。开发者可以编写自定义的 Visitors,通过遍历 AST 来访问特定类型的节点,执行代码分析、重构、生成等任务。
com.github.javaparser.ast.visitor.GenericVisitor
和com.github.javaparser.ast.visitor.VoidVisitor
这两个访问器提供了默认实现,如果需要自定义访问器,可以继承它们来实现自己的业务逻辑。
5. Printer(打印器):这个也很好理解,Printer 用于将 AST 转换回 Java 源代码的字符串表示形式。它可以将修改后的 AST 打印回原始源代码文件,或将 AST 打印为格式化的代码字符串。在上一章节的最后提到的CompilationUnit重写的toString方法,实际上就是使用了Printer来完成AST到源码字符串的转换。
上面的一些组件是javaParser中比较核心且常用的部分,当然javaParser还提供了一些便捷的工具类以及用法,这些内容笔者也没有接触过,有需要的读者可以自行翻阅文档。
工具使用方式
第一章提到的jar包和源码均已上传私服,可以直接通过maven插件的方式运行。
添加依赖
<dependency> <groupId>com.jd.omni.opdd</groupId> <artifactId>lombok-replace</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
添加maven插件
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.0.0</version> <executions> <execution> <goals> <goal>java</goal> </goals> </execution> </executions> <configuration> <mainClass>com.jd.omni.opdd.tools.lombok.LombokConverter</mainClass> <arguments> <argument>../../pop-jingme-customs</argument> </arguments> </configuration> </plugin>
插件中的argument节点需要替换成工程的路径,可以是绝对路径也可以是相对路径
运行插件
执行 mvn exec:java
可以在控制台看到:
注意事项
使用工具处理完成后,一定要build的一下检查是否有编译错误,虽然在删除操作时做了较为严苛的校验,但是有些特殊的变量名可能没有考虑到,这部分问题是可以通过编译检查出来的。
另外,对于没有引用lombok的模块,需要手动添加依赖。
写在最后
代码重构应该像手术刀一样,快、准、狠,正所谓君子生非异也,善假于物也。本文主要起一个抛砖引玉的作用,重点在于JavaParser的介绍,笔者写的这个小工具非常简单,之前也写过B-PaaS一键生成matrix.json,一键根据错误码定义生成i18n文件,大都不难。
如果发散性思考一下,可以通过JavaPaser结合其他平台提供的open api做一些有趣的事情,例如结合JSF、UMP、pfinder的API,实现对无调用方的方法清理。
除了代码重构,拿到了语法树后也可以做一些代码可视化的工具,参考之前发布的谢骁同学写的《浅谈代码可视化》。
作者:京东零售 谭磊
来源:京东云开发者社区 转载请注明来源

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
亿级流量高并发春晚互动前端技术揭秘
前言 2022年1月,京东成为央视总台2022年春节联欢晚会独家互动合作伙伴,双方在红包互动、电商等方面展开全方位深度合作。在除夕当天产生691亿次互动,送出15亿元红包好物。 如何在这种大规模、高并发的场景下,确保系统的稳定性和性能,为用户提供稳定流畅的互动体验,成为了我们亟待解决的问题。 接下来我们主要从静态资源优化、缓存、容错、工程化几个方面来详细介绍前端团队所做的努力和创新。 静态资源优化 首屏资源加载策略 在春晚主持人口播之后,大量用户会集中在一段时间内涌入互动页面,这会导致流量峰值。为了降低页面打开时的请求次数和资源体积,我们根据页面交互,将所需资源分为三类:首屏、次屏以及操作后。 首屏资源主要包括:HTML文档、JavaScript、CSS以及样式图片。由于这是单页面应用,我们可以通过常规技术将JS和CSS进行打包。对于样式图片,我们可以通过按需加载的方式,显著减小首屏资源体积。 页面包含两个楼层,首屏的互动楼层和次屏的万券齐发楼层。其中,首屏会展示两排优惠券,因此,我们需要在首屏加载这部分券楼层的样式图片。互动主玩法中主要包括抽奖弹窗、邀人弹窗和击鼓游戏。通过拆分优化,...
- 下一篇
告别 GPU 焦虑,玩转极致性价比的 CPU 文生图
作者:壮怀、竹刚 AIGC 中的 Stable Diffusion 文生图模型是开源流行的跨模态生成模型,用于生成给定文本对应的图像。但由于众所周知的原因,GPU 资源出现了一卡难求的现状,如何通过云计算快速提升业务规模,降低文生图的计算成本,以及更好的保护自定义的扩展模型?针对文生图模型特性和规模化场景,本文提供了一种新的思路,通过云原生部署方式提供推理服务 API,使用 CPU 矩阵计算能力针对模型进行无侵入优化,以及机密计算的环境的无缝切换,可以有效的替代部分 GPU 推理需求,提供稳定、高效、高性价比且安全的文生图服务。 通过在 Kubernetes 集群内添加阿里云第八代企业级 CPU 实例 g8i,不修改模型本身,通过云原生化的部署和推理优化,在 CPU 节点上实现秒级响应的成本低廉的文生图服务。本文介绍如何在 ACK 集群中快速部署一个使用 CPU 加速的 Stable Diffusion 文生图示例服务,并且您还可以将这个示例服务无缝迁移到机密虚拟机节点池中,为您的推理服务提供数据安全保护。 准备环境 在 ACK 集群内创建一个使用阿里云第八代企业级实例 g8i 的节点...
相关文章
文章评论
共有0条评论来说两句吧...