Java编译期注解处理器AbstractProcessor使用

我们接触的注解主要分为以下两类

  1. 运行时注解:通过反射在运行时动态处理注解的逻辑
  2. 编译时注解:通过注解处理器在编译期动态处理相关逻辑

编译期注解我们常用的有Lombok,在class文件中自动生成get和set方法

解编译期处理流程最关键的一个类就是javax.annotation.processing.Processor注解处理器的接口类,遵循SPI规约进行拓展,我们所有需要对编译期处理注解的逻辑都需要实现这个Processor接口,当然,AbstractProcessor 抽象类帮我们写好了大部分都流程,所以我们只需要实现这个抽象类就可以很方便的定义一个注解处理器

自定义注解处理器

(1)tools.jar加入到idea的类路径

注意:在idea自定义编译处理器前,需要把tools.jar加入到idea的类路径中(文件--》项目结构--》平台设置--》SDK-->类路径--》把tools.jar加入进去),如下图:

(2)建maven父子项目

1)父项目demo的pom.xml配置如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wbq</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1</version>
    <packaging>pom</packaging>
    <name>demo</name>
    <description>demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <modules>
        <module>child1</module>
        <module>child2</module>
        <module>child3</module>

    </modules>
    <dependencies>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions><!-- 去掉默认配置 -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--  log4j2依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
            <version>2.7.3</version>
        </dependency>
        <!-- hutool -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.6</version>
        </dependency>

    </dependencies>


    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>

                </configuration>

            </plugin>

        </plugins>
    </build>


</project>
2)子项目child3的pom.xml如下
  • pom.xml
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>demo</artifactId>
        <groupId>com.wbq</groupId>
        <version>0.0.1</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>child3</artifactId>

    <dependencies>

        <!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.2</version>
        </dependency>

    </dependencies>

    <build>
        <!-- 指定JDK编译版本 -->
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                    <compilerArgs>
                        <arg>-proc:none</arg>
                    </compilerArgs>
                    <compilerArguments>
                        <bootclasspath>
                            ${java.home}/lib/rt.jar;${java.home}/lib/jce.jar;${java.home}/../lib/tools.jar
                        </bootclasspath>
                    </compilerArguments>
                </configuration>


            </plugin>

        </plugins>


    </build>

</project>
  • 注解类
package com.wbq.child3.processor;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//源码级注解,编译结束就丢弃
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyFieldAnnotation {

}
  • AbstractProcessor实现类
    在有MyFieldAnnotation注解的类的方法中添加代码:System.out.println("hello world");
package com.wbq.child3.processor;

import com.sun.tools.javac.api.JavacTrees;
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.tree.TreeTranslator;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Names;

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

/**
 * 在有MyFieldAnnotation注解的类的方法中添加代码:System.out.println("hello world");
 */
@SupportedAnnotationTypes("com.wbq.child3.processor.MyFieldAnnotation")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
//@AutoService(Processor.class)
public class MyFieldProcessor extends AbstractProcessor {
    /**
     * 抽象语法树
     */
    private JavacTrees javacTrees;
    /**
     * AST
     */
    private TreeMaker treeMaker;
    /**
     * 标识符
     */
    private Names names;
    /**
     * 日志处理
     */
    private Messager messager;
    private Filer filer;
    public synchronized void init(ProcessingEnvironment processingEnv) {

        System.out.println("初始化");
        processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, "初始化 ");
        javacTrees = JavacTrees.instance(processingEnv);
        Context context = ((JavacProcessingEnvironment)processingEnv).getContext();
        this.treeMaker = TreeMaker.instance(context);
        super.init(processingEnv);
        this.names = Names.instance(context);
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        System.out.println("注解处理器");
        annotations.stream().flatMap(t -> roundEnv.getElementsAnnotatedWith(t).stream())
                .forEach(t -> {
                    JCTree tree = javacTrees.getTree(t);
                    tree.accept(new TreeTranslator() {
                        @Override
                        public void visitMethodDef(JCTree.JCMethodDecl tree) {
                            System.out.println("hello world");
                            JCTree.JCStatement sysout = treeMaker.Exec(
                                    treeMaker.Apply(
                                            List.nil(),
                                            select("System.out.println"),
                                            List.of(treeMaker.Literal("hello world"))
                                    )
                            );
                            //覆盖原有的语句块
                            tree.body.stats = tree.body.stats.append(sysout);
                            super.visitMethodDef(tree);
                        }
                    });
                });
        return true;
    }

    private JCTree.JCFieldAccess select(JCTree.JCExpression selected,String expressive){
        return treeMaker.Select(selected, names.fromString(expressive));
    }

    private JCTree.JCFieldAccess select(String expressive){
        String[] exps=expressive.split("\\.");
        JCTree.JCFieldAccess access=treeMaker.Select(ident(exps[0]),names.fromString(exps[1]));
        int index=2;
        while(index<exps.length){
            access=treeMaker.Select(access, names.fromString(exps[index++]));
        }
        return access;
    }
    private JCTree.JCIdent ident(String name){
        return treeMaker.Ident(names.fromString(name));
    }


}
  • 指定插入式注解类

在resources下新建META-INF文件夹,META-INF文件夹下新建services文件夹,services文件夹下新建文件(文件名=javax.annotation.processing.Processor)

src/main/resources/META-INF/services/javax.annotation.processing.Processor

javax.annotation.processing.Processor文件中写入

com.wbq.child3.processor.MyFieldProcessor

3)新建子项目child2

child2使用child3中的注解

结构如下:

  • pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>demo</artifactId>
        <groupId>com.wbq</groupId>
        <version>0.0.1</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>child2</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>

        <dependency>
            <groupId>com.wbq</groupId>
            <artifactId>child3</artifactId>
            <version>0.0.1</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
  • 测试类如下:
package com.wbq.child2;


import com.wbq.child3.processor.MyFieldAnnotation;
//child3中的注解
@MyFieldAnnotation
public class TestChild3Main {
    public static void main(String[] args) {

        System.out.println("main");
    }
}

(3)测试运行

  • 在maven中先编译child3,依次:clean、compile、package、install

在maven中编译child2,依次:clean、compile

在child2\target\classes\com\wbq\child2中生成了TestChild3Main.class文件,使用idea打开这个class文件,Main方法中添加了一行代码System.out.println("hello world");

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数字乡村创新实践探索农业现代化与乡村振兴新路径:科技赋能农村全面振兴与农民福祉新纪元

目录 引言 一、数字乡村与农业现代化新路径 1、智慧农业引领农业现代化 2、农业产业链的数字化转型 二、数字乡村与乡村振兴新路径 1、农村信息化水平的提升 2、农村治理模式的创新 三、科技赋能农村全面振兴与农民福祉新纪元 1、提升农业生产效益与农民收入 2、促进…

【Qt 学习笔记】Qt常用控件 | 按钮类控件Push Button的使用及说明

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 按钮类控件Push Button的使用及说明 文章编号&#xff1…

路径规划 | 基于蜣螂优化算法的无人机三维路径规划(Matlab)

目录 效果一览基本介绍程序设计参考文献 效果一览 基本介绍 基于蜣螂优化算法的无人机三维路径规划【23年新算法应用】可直接运行 Matlab语言 1.读取地形数据&#xff0c;利用蜣螂算法DBO优化三维路径&#xff0c;目标函数为总路径最短&#xff0c;同时不能撞到障碍物&#xff…

Android Studio使用USB真机调试详解

本文为大家分享了Android Studio使用USB真机调试的具体方法&#xff0c;供大家参考&#xff0c;具体内容如下 以小米4为例&#xff0c;先将手机通过USB连接电脑&#xff0c;在设备管理器中确保驱动安装正确。 对手机的设置 1.设置手机为开发者模式&#xff08;设置- 关于手机…

windows应急响应基础知识

一、系统排查 1、系统详细信息 systeminfo2、网络链接 netstat -ano LISTENING 服务启动后首先处于侦听 ESTABLISHED 建立连接。表示两台机器正在通信。 CLOSE_WAIT 对方主动关闭连接或者网络异常导致连接中断&#xff0c;这时我方的状态会变成CLOSE_WAIT 此时我方要调用…

如何查找overlayfs对应的POD如何根据pod找到containerd id

如何查找overlayfs对应的POD mount |grep overlayfs | grep 1738 ctr -n k8s.io c list | grep 11ac4083419be11174746b68d018a0a402d9ae43c6b52125810fe1ec7db63bc6 查找目录并统计大小 find / -name "jfsCache" -exec du -sh {} | sort -rh如何根据pod找到c…

HarmonyOS4-网络连接-http请求数据

使用Axios发送请求&#xff1a; 详细资料来源于官方文档。

java数据结构与算法刷题-----LeetCode338. 比特位计数

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 位运算统计1的个数动态规划 位运算统计1的个数 &#x1f3c6;Le…

2023年图灵奖揭晓,你怎么看?

Avi Wigderson——理论计算机科学的先锋&#xff0c;荣获2023年图灵奖 在科技界&#xff0c;图灵奖堪称与诺贝尔奖齐名的崇高荣誉&#xff0c;它每年授予对计算机行业的贡献达到重大突破的个人或团队。今年&#xff0c;这一声誉卓著的奖项被授予了普林斯顿大学的数学教授 Avi …

上位机图像处理和嵌入式模块部署(树莓派4b安装opencv)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 树莓派4b上面安装的镜像应该是debian系统&#xff0c;本身是可以用apt-get进行软件下载的。这一点对于我们来说就非常的方便。因为&#xff0c;如果…

毕设选51还是stm32?51太简单?

如果你更倾向于挑战和深入学习&#xff0c;STM32可能是更好的选择。如果你希望更专注于底层硬件原理&#xff0c;51可能更适合。我这里有一套嵌入式入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习嵌入式&#xff0c;不妨点个关注&#xff…

Spring Boot | SpringBoot对 “SpringMVC“的 “整合支持“、SpringMVC“功能拓展实现“

目录: SpringMVC 的 “整合支持” ( 引入"Web依赖启动器"&#xff0c;几乎可以在无任何额外的配置的情况下进行"Web开发")1.SpringMVC "自动配置" 介绍 ( 引入Web依赖启动器"后&#xff0c;SpringBoot会自动进行一些“自动配置”&#xff0…

计算机网络 Cisco路由器基本配置

一、实验内容 1、按照下表配置好PC机IP地址和路由器端口IP地址 2、配置好路由器特权密文密码“abcd&#xff0b;两位班内序号”和远程登录密码“star” 3、验证测试 a.验证各个接口的IP地址是否正确配置和开启 b.PC1 和 PC2 互ping c.验证PC1通过远程登陆到路由器上&#…

Linux笔记之查看docker容器目录映射

Linux笔记之查看docker容器目录映射 —— 2024-04-15 code review! docker inspect 容器ID或容器名 | grep -A 20 Mounts实践 grep -A 参数详解&#xff1a; grep 的 -A 参数用于在输出中包括匹配行后的指定数目的行。 使用 -A 参数 该参数的基本语法如下&#xff1a; …

[大模型]InternLM2-7B-chat FastAPI 部署

InternLM2-7B-chat FastAPI 部署 InternLM2 &#xff0c;即书生浦语大模型第二代&#xff0c;开源了面向实用场景的70亿参数基础模型与对话模型 &#xff08;InternLM2-Chat-7B&#xff09;。模型具有以下特点&#xff1a; 有效支持20万字超长上下文&#xff1a;模型在20万字…

Mini-Gemini: 探索多模态视觉语言模型的新境界

一、背景 在数字化时代&#xff0c;人工智能的发展正以前所未有的速度推进。特别是在多模态学习领域&#xff0c;结合视觉和语言的能力已成为研究的热点。最近&#xff0c;一篇名为“Mini-Gemini: Mining the Potential of Multi-modality Vision Language Models”的文章在arX…

基于SSM项目个人健康信息管理系统

采用技术 基于SSM项目个人健康信息管理系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringMVCMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 用户端 用户首页 健康知识 用户注册 医院推荐信息 系统概要…

linux 云计算平台基本环境(知识准备篇)

为了更多的了解云计算平台&#xff0c;结合云计算和linux的知识写了一篇云计算的介绍和汇总。 文章目录 前言1. centos的软件管理1.1 yum软件包管理1.1.1 yum命令语法&#xff1a;1.1.2 安装软件包的步骤1.1.3 yum源 2. 主机名管理与域名解析3. centos的防火墙管理4. openstack…

以pytorch pipeline并行为例,分析各kernel的耗时占比及性能瓶颈

以pytorch pipeline并行为例,分析各kernel的耗时占比及性能瓶颈 1.生成pipeline并行的测试代码2.pipeline profing3.生成nsys2json.py代码4.将nsys sqlite格式转chrome json格式5.生成耗时成分统计代码6.统计耗时成分7.耗时成分如下:8.查看GPU PCIE链路状态9.链路状态如下10.Ns…

jetson系列开发板使用虚拟机烧录系统时,遇见无法识别开发板的情况

在双系统中的ubuntu系统烧录没问题&#xff0c;但是电脑Ubuntu系统由于版本低&#xff0c;所以没有网络&#xff0c;烧录起来还的连网线&#xff0c;所以问了开发板的工程师&#xff0c;所幸&#xff0c;解决了问题&#xff0c;很感谢工程师的指导&#xff0c;特此记录一下&…