• java AbstractProcessor 编译时注解 (JSR 269)


    写在前面

    下一篇:java AbstractProcessor 编译时注解(API)

    Lombok 的getter、setter如何实现的?

    答案就在AbstractProcessor 身上,继承AbstractProcessor 抽象类,java文件在编译时编译器会检查AbstractProcessor的子类,并根据这些子类的内容,对java文件进行动态修改,再生成class文件。

    1、实现编译时注解

    注意:不要将AbstractProcessor 和 使用该AbstractProcessor 的类写在同一个项目中

    1.1、实现步骤

    以maven项目为例(将实现编译时注解的功能放到项目b ,测试使用这个功能在项目a)

    项目结构:

    在这里插入图片描述

    1.1.1、项目b的内容

    b的pom.xml

        <properties>
            <maven.compiler.source>1.8maven.compiler.source>
            <maven.compiler.target>1.8maven.compiler.target>
        properties>
    
        <dependencies>
    
            
            
            <dependency>
                <groupId>com.google.auto.servicegroupId>
                <artifactId>auto-serviceartifactId>
                <version>1.0-rc5version>
            dependency>
    
            
            <dependency>
                <groupId>com.sungroupId>
                <artifactId>toolsartifactId>
                <version>1.8version>
                <scope>systemscope>
                <systemPath>${java.home}/../lib/tools.jarsystemPath>
            dependency>
    
        dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    b的HelloWorld.java

    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.SOURCE)
    public @interface HelloWorld {
    }
    
    • 1
    • 2
    • 3
    • 4

    b的MyProcessor.java

    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.Iterator;
    import java.util.Set;
    
    @SupportedAnnotationTypes("cc.HelloWorld")
    @SupportedSourceVersion(SourceVersion.RELEASE_7)
    @AutoService(Processor.class)
    public class MyProcessor extends AbstractProcessor {
        @Override
        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
            Context context = ((JavacProcessingEnvironment) this.processingEnv).getContext();
            JavacElements elementUtils = (JavacElements) this.processingEnv.getElementUtils();
            TreeMaker treeMaker = TreeMaker.instance(context);
    
            JCTree.JCMethodDecl jcMethodDecl;
            for (Iterator var7 = roundEnv.getElementsAnnotatedWith(HelloWorld.class).iterator(); var7.hasNext(); jcMethodDecl.body = treeMaker.Block(0L, 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("这是HelloWorld打印的")))), jcMethodDecl.body))) {
                Element element = (Element) var7.next();
                jcMethodDecl = (JCTree.JCMethodDecl) elementUtils.getTree(element);
                treeMaker.pos = jcMethodDecl.pos;
            }
            return false;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    1.1.2、项目a的内容

    a的pom.xml

        <properties>
            <maven.compiler.source>1.8maven.compiler.source>
            <maven.compiler.target>1.8maven.compiler.target>
        properties>
        <dependencies>
            
            <dependency>
                <groupId>org.examplegroupId>
                <artifactId>bartifactId>
                <version>1.0version>
                <scope>compilescope>
            dependency>
        dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    a的Test.java

    import cc.HelloWorld;
    
    public class Test {
        @HelloWorld
        public static void main(String[] args) {
            System.out.println("这是Test自己打印的");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    启动Test试试

    在这里插入图片描述
    看一下编译后的文件Test.class

    在这里插入图片描述
    Test.class有两行System.out.println,一行是Test.java原本就有的,一行是@HelloWorld注解动态加入的

    1.2、问题与报错

    1、java: 服务配置文件不正确, 或构造处理程序对象javax.annotation.processing.Processor…
    在这里插入图片描述
    解决方法:这可能是由于动态注解的代码有改动,但未重新编译class文件造成的,删掉target重新编译即可

    2、注解没效果
    解决方法:你可能将AbstractProcessor的定义与使用放在了同一个项目中,不要将AbstractProcessor 和 使用该AbstractProcessor 的类写在同一个项目中,会因为AbstractProcessor 没有预编译导致报错或没效果

    2、相关API

    参考下一篇:java AbstractProcessor 编译时注解(API)

  • 相关阅读:
    从此刻开始走进HTML的大门!!!
    kuka协作机器人LBR系列 issy15R930导入到ros2_rviz(带外观文件)
    web网页设计期末课程大作业:旅游网页主题网站设计——中国风的温泉酒店预订网(13页)HTML+CSS+JavaScript
    群晖7.2版本通过Container Manager安装xiaoya-alist
    Swift 周报 第十三期
    在.NET 6.0中配置WebHostBuilder
    NativeBuferring,一种零分配的数据类型[下篇]
    抖音新接口——关键词月搜查询 API
    CU-Mamba:具有通道学习功能的选择性状态空间模型用于图像恢复
    Java学习笔记(十五):IO流
  • 原文地址:https://blog.csdn.net/a__int__/article/details/127447945