AbstractProcessor相关的API记录

news2025/7/11 1:50:45

java文件操作相关的两个类: JCTree 树节点、TreeMaker 树节点构建器。


JCTree

JCTree的一个子类就是java语法中的一个节点,类、方法、字段等这些都被封装成了一个JCTree子类。

JCTree详细的介绍:抽象语法树AST的全面解析(二) - 简书

TreeMaker

TreeMaker 里的方法用于构建JCTree某个子类,例:treeMaker.MethodDef(…)返回值是JCTree的子类JCMethodDecl(方法节点)

TreeMaker创建各种节点的方法如下:

// public访问修饰符
JCTree.JCModifiers publicDot = treeMaker.Modifiers(Flags.PUBLIC);
// void关键字
JCTree.JCPrimitiveTypeTree voidDot = treeMaker.TypeIdent(TypeTag.VOID);
// 空语句
JCTree.JCBlock emptyDot = treeMaker.Block(0, List.nil());
// 一个无参构造方法
JCTree.JCMethodDecl noArgsMethod = treeMaker.MethodDef(
                    publicDot,
                    names.fromString("<init>"),
                    voidDot ,
                    List.nil(),
                    List.nil(),
                    List.nil(),
                    emptyDot,
                    null);



// this关键字
JCTree.JCIdent thisDot = treeMaker.Ident(names.fromString("this"));
// userPassword     (Name类型可以是方法名、字段名、变量名、类名)
Name userPasswordName = names.fromString("userPassword");
// this.userPassword  (访问当前方法中的字段userPassword)
JCTree.JCFieldAccess thisUserPassword = treeMaker.Select(thisDot , userPasswordName);
// userPassword 变量
JCTree.JCIdent userPassword = treeMaker.Ident(userPasswordName);
// this.userPassword = userPassword       (treeMaker.Apply()以及treeMaker.Assign()需要外面包一层treeMaker.Exec())
treeMaker.Exec(treeMaker.Assign(thisUserPassword, userPassword)); 

 如以下代码是给一个方法新增一句话System.out.println("hello world")

package jst;

import com.google.auto.service.AutoService;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import java.util.Set;

/**
 * @author wuweifeng wrote on 2022/12/21
 * @version 1.0
 */
@SupportedAnnotationTypes("jst.HelloWorld")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@AutoService(Processor.class)
public class MyProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        Set<? extends Element> elements = roundEnv.getRootElements();
        final Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
        final JavacElements elementUtils = (JavacElements) processingEnv.getElementUtils();
        final TreeMaker treeMaker = TreeMaker.instance(context);

        for (Element element : roundEnv.getElementsAnnotatedWith(HelloWorld.class)) {
            JCTree.JCMethodDecl jcMethodDecl = (JCTree.JCMethodDecl) elementUtils.getTree(element);

            treeMaker.pos = jcMethodDecl.pos;
            jcMethodDecl.body = treeMaker.Block(0, List.of(
                    treeMaker.Exec(
                            treeMaker.Apply(
                                    List.nil(),
                                    treeMaker.Select(
                                            treeMaker.Select(
                                                    treeMaker.Ident(
                                                            elementUtils.getName("System")
                                                    ),
                                                    elementUtils.getName("out")
                                            ),
                                            elementUtils.getName("println")
                                    ),
                                    List.of(
                                            treeMaker.Literal("Hello, world!!!")
                                    )
                            )
                    ),
                    jcMethodDecl.body
            ));
        }
        return false;
    }

}

使用时

@HelloWorld
    public static void main(String[] args) {
        System.out.println("demo打印");
    }

加上了@HelloWorld注解后,运行就会打印

现在针对MyProcessor类里的内容做个解释。

jcMethodDecl.body即为方法体,利用treemaker的Block方法获取到一个新方法体,将原来的替换掉。就达到了修改方法体的目的了。这里的Block方法有两个参数,重点要关注的是第二个参数,也就是具体的方法体内容。它是一个List类型的参数,List里面每一个元素就代表一个语句块,比如,例子中有两块语句,第一块是我们织入的代码块:System.out.println("Hello, world!!!");用treeMaker.Exec()来实现,第二块是原来的代码块:jcMethodDecl.body。这块的代码是用户原本的代码,我们直接放进来就行。这个List是有顺序的,谁的顺序在前,谁最终生成的代码块就在前,比如这里我们织入的代码在原来的代码块之前,所以最终生成System.out.println("Hello, world!!!");语句就在该方法的第一行位置。

重点关注的应该是treeMaker.Exec()这个方法,这个方法帮助我们最终生成了System.out.println("Hello, world!!!");这条语句,它的参数是treeMaker.Apply这个方法的返回结果,这个方法的第二个参数,也就是最终实现了输出System.out.println("Hello, world!!!")的东西。

这里面用到了两个方法,一个是treeMaker.Select(生成具体的方法),一个是treeMaker.Literal(方法的参数)。treeMaker.Select里面套了很多层,对比两种写法的区别,你也能明白,这是为了写出多级方法的做法,多级方法的第一级以treeMaker.Ident开始,然后一层套一层,直到整个方法结束。

如何debug processor代码

a)idea右上角,Edit Configurations

b)点击左上角的+号,选择Remote,或者如图的Remote JVM debug

 

c)随便起一个名字,比如ProcessorDebug,如图,点击确定。

d)进入Terminal界面,输入mvnDebug clean install,回车,不出意外的话,会出现如图的提示

f)process里面打上断点,然后点击debug按钮,便命中了断点

 

异常情况 

如果在rebuild project时出现:java: java.lang.ClassCastException: com.sun.proxy.$Proxy26 cannot be cast to com.sun.tools.javac.processing.JavacProcessingEnvironment

则在设置里添加如下内容:

-Djps.track.ap.dependencies=false

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/109011.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据驱动测试】从方法探研到最佳实践

导读 在自动化测试实践中&#xff0c;测试数据是制造测试场景的必要条件&#xff0c;本文主要讲述了在沟通自动化框架如何分层&#xff0c;数据如何存储&#xff0c;以及基于单元测试pytest下如何执行。并通过实践案例分享&#xff0c;提供数据驱动测试的具体落地方案。 基本…

训练yolo系列+deepsort模式的跟踪器(一):训练deepsort

由于是检测+跟踪模式,因此检测器和跟踪器是分开训练的。本节中我们先手把手的训练deepsort跟踪器。在此要感谢mikel大佬所提供的源码,由于代码更新的比较频繁,各种版本错误和运行错误在本节中会重点说明。mikel-brostrom/Yolov5_StrongSORT_OSNet: Mult-object tracking and…

python之环境切换问题实践总结

前言 这个标题是实践总结&#xff0c;为什么呢&#xff0c;因为这个问题困扰了我整整一个月&#xff0c;都没有解决。现在终于解决了&#xff0c;写一篇文章记录一下&#xff0c;也看看有没有小伙伴遇到一样的问题&#xff0c;或者在我下次还会发生这样的实情事可以第一时间解…

GAMES101 Assignment 3

前言 通过阅读实验提供的代码框架&#xff0c;可以加深对渲染管线的理解。assignment1,2我并没有做&#xff0c;我们课程图形学本来有实验计划&#xff0c;然而老师专门让我们做GAMES101的这个实验&#xff0c;其意义可见一斑。 阅读过程中遇到许多困难&#xff0c;看了许多资…

线性杂双功能PEG试剂Biotin-PEG-Silane,Silane-PEG-Biotin,生物素-PEG-硅烷

英文名称&#xff1a;Biotin-PEG-Silane&#xff0c;Silane-PEG-Biotin 中文名称&#xff1a;生物素-聚乙二醇-硅烷 生物素-PEG-硅烷是一种含有生物素和硅烷的线性杂双功能PEG试剂。它是一种有用的带有PEG间隔基的交联或生物结合试剂。生物素能与亲和素和链霉亲和素结合&…

多期DID和事件研究法含文献和do代码

多期DID和事件研究法含文献和do代码 1、方法&#xff1a;多期DID 2来源&#xff1a;JDE发表的一篇多期DID和事件研究法相关的文章&#xff0c; 文章名为为"Here waits the bride? The effect of Ethiopias child marriage law"。 3、数据内容&#xff1a;数据包…

钱为什么会贬值?

一、什么是钱贬值&#xff1f; 当我们在谈钱贬值的时候&#xff0c;我们是在说什么&#xff1f; 是指的今天5块钱可以买5个苹果&#xff0c;1个月后5块钱只可以买3个苹果.&#xff08;以商品为评价基准&#xff09; 是指的今天1美元可以换6元人民币&#xff0c;1个月后1美元…

数据库实验5 数据库设计实验

前言&#xff1a;不知道啥原因&#xff0c;最后设计出来少了一个表&#xff0c;无语 实验5 数据库设计实验 1.实验目的 掌握数据库设计基本方法及数据库设计工具。 2.实验内容和要求 掌握数据库设计基本步骤,包括数据库概念结构设计、逻辑结构设计,物理结构设计,数据库模式…

Flarum部署:从源码到docker到放弃

警告&#xff1a; 此篇文章前半段记录了我用代码部署flarum遇到的一些问题和解决办法&#xff0c;但是可能是由于我是在不熟悉php的框架结构&#xff0c;最终我还是选择了使用docker进行部署&#xff0c;请斟酌是否继续阅读本文。 Hello&#xff0c;大家好&#xff0c;我是内网…

开源项目-OA自动化管理系统

哈喽&#xff0c;大家好啊&#xff0c;今天给大家带来一个开源系统-办公自动化管理系统 简介: OA( Office Automation System)办公自动化系统是一个企业用来管理日常事务的系统&#xff0c;它一般用来管理各种流程&#xff08;报销、请假. . .&#xff09;审批&#xff0c;通讯…

Fabric.js 元素中心缩放

本文简介 点赞 关注 收藏 学会了 使用 fabric.js 创建的图形&#xff0c;默认的缩放原点是元素操作点的对角点。 如下图所示&#xff1a; 如果按住 alt 键 操作会把原点移动到元素中心。 如下图所示&#xff1a; 如果想将默认缩放操作设置为“中心缩放”&#xff0c;只需…

ImportError: DLL load failed while importing etree: 找不到指定的模块。

目录标题前言错误描述报错代码如下&#xff1a;原因&#xff1a;解决办法前言 今天我正在悠闲的逛着网站寻找今天要爬取的目标当我找到目标的时候正要创建我的scrapy爬虫文件的时候竟然报错了我很惊讶&#x1f62e;&#x1f62e;&#x1f62e;&#xff01;&#xff01;&#x…

安全分析模型核心服务部署

安全分析模型核心服务部署 ModelOps 对所有的人工智能 模型&#xff08;图形模型、语言模型、基于规则的模型&#xff09;以及决策模型的整个生命周期 进行管理&#xff0c;确保对生产中的所有模型进行独立验证和问责&#xff0c;其核心功能涵盖了模型存储、模型测试、模型回滚…

非零基础自学Golang 第15章 Go命令行工具 15.6 性能分析 15.6.1 安装Graphviz

非零基础自学Golang 文章目录非零基础自学Golang第15章 Go命令行工具15.6 性能分析15.6.1 安装Graphviz第15章 Go命令行工具 15.6 性能分析 性能分析和调优是一种强大的技术&#xff0c;用于验证是否满足实际性能要求。 Go语言支持使用go tool pprof工具进行性能查看及调优。…

DNS协议分析

上一篇文章从工作原理角度分析了DNS的作用与意义&#xff0c;这次来看看DNS到底是以什么形式进行通信的。 DNS报文格式如下所示&#xff1a; DNS报文由12字节长的首部和4个长度可变的字段组成。 1.标识&#xff0c;由主机端设置&#xff0c;为的是唯一标识当前DNS报文。 2.1…

关于Docker入门

目录 1.Docker简介 2.Centos7安装Docker 3.Docker HelloWorld运行原理解析 4.阿里云镜像仓库 5.Docker命令 Docker基本命令 Docker镜像常用命令 Docker 容器常用命令 1.Docker简介 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从Apache2.0协议开源 Doc…

Vue3——vuex的使用——axios网络请求的使用

vuex作用&#xff1a;用来集中式管理数据 集中式的应用&#xff0c;当前有四个组件A,B,C,D&#xff0c;假如现在有一个数据x在A里面&#xff0c;现在其他三个组件都要用到x并且好要修改x的时候&#xff0c;有一种方法就要用到全局事件总线&#xff0c;如下图所示 像上面这样不…

用于生成随机曲面的Matlab程序(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 本文在总结、分析现有随机图形生成方法的基础上&#xff0c;结合自由形状的造型技术、自适应神经网络的自适应学习机理&#x…

科研人快速入门LaTex到日常使用,下载安装配置,语法使用说明等

1 前言 Latex是一款开源免费并且应用相当广泛的排版工具&#xff0c;被⼴泛运⽤在各个⾏业&#xff0c;⽐如学术界、出版界。LaTeX 和 Word 相比&#xff0c;LaTeX 入门者更能写出漂亮的文档。它不但能对文字、公式、图片进行精确而复杂的排版&#xff0c;并且还能保证全文各个…

【OpenFeign】【源码+图解】【四】FeignClient实例工具类ReflectiveFeign

【OpenFeign】【源码图解】【三】FeignClient的配置信息 目录5. FeignClient实例工具类ReflectiveFeign5.1 增强Builder属性5.1.1 Capability5.2 创建ReflectiveFeign5. FeignClient实例工具类ReflectiveFeign 上文中调用了targeter.target(this, builder, context, target)&a…