Java annotation processor 拿到被注解文件的内容 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
asanelder
V2EX    Java

Java annotation processor 拿到被注解文件的内容

  •  
  •   asanelder 2020 年 6 月 1 日 2934 次点击
    这是一个创建于 2153 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有一个这样的注解

    @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface Question {} 

    被注解的文件如下

    @Question public class SomeQuestion { public void foo(){} } 

    现在的问题是,我想在 annotation processor 中,拿到被注解文件的源代码,这里就是

    public class SomeQuestion { public void foo(){} } 

    如何做到呢?求助!

    第 1 条附言    2020 年 6 月 1 日
    我的意思是,有没有相关的 annotation api 可以得到 source code. 比如说 TypeElement 就已经表示源文件中的一个类型结构了,按道理来说,通过 TypeElement 就可以得到它所表示的结构信息,也就是相关的 souce code,但我找了半天,好像没有。
    第 2 条附言    2020 年 6 月 2 日

    添加一个stackoverflow上的回答吧。以下

    Java's standard annotation processors provide a callback only at declarations, such as method and field declarations.

    It's possible to use an annotation processor to analyze expressions, but it's a bit more work. You will have to write an annotation processor that, at each method, obtains the AST (abstract syntax tree or parse tree) for the method and then visits each expression in the method. The AST is compiler-specific.

    The two best-known projects that do this are the Checker Framework and Project Lombok. Maybe you could take inspiration from their implementations, or even write your annotation processor on top of one of them.

    大概意思是,java annotation processer 只能拿到声明级别的信息,如类,方法的声明相关信息,拿不到其定义的内容。要想拿到类和方法定义的具体内容,需要使用到AST。

    鉴于我的需要只是拿到源文件的内,我还是使用读取文件的方式好了。。。

    19 条回复    2020-06-02 15:08:12 +08:00
    freebird1994
        1
    freebird1994  
       2020 年 6 月 1 日 via Android
    将类注入到 spring 容器中。实现 beanPostProcessor 。可以对注入容器的 bean 进行操作
    freebird1994
        2
    freebird1994  
       2020 年 6 月 1 日 via Android
    @freebird1994 我好像理解错了楼主的意思?拿源代码?这个怕是只能通过类似 asm 等去获取字节码吧?还能拿到源代码么…看下楼下有没有大佬指点一下
    luckylo
        3
    luckylo  
       2020 年 6 月 1 日 via Android
    个人觉得不可能。注解只在源代码中生效,编译后被擦除了。根本不能拿到任何东西
    fantastM
        4
    fantastM  
       2020 年 6 月 1 日
    楼主说的 annotation processor 应该是 https://docs.oracle.com/javase/8/docs/api/javax/annotation/processing/AbstractProcessor.html

    这是作用在 javac 阶段的,类似于 Lombok 的注解
    Jrue0011
        5
    Jrue0011  
       2020 年 6 月 1 日
    额。。反正是源码级别,获取到类名后根据是外部类、内部类在整个项目目录下找对应的源码文件读取?
    inwar
        6
    inwar  
       2020 年 6 月 1 日 via Android
    想到个思路,打包的时候把源码复制一份到 resource, 注解改成 runtime,获取带包名的类名, 根据长类名读取 resouece 目录下源码文件。

    有点黑魔法,不知道楼下有没有好的方案
    Jrue0011
        7
    Jrue0011  
       2020 年 6 月 1 日
    @Jrue0011 就是 4L 说的注解处理器
    Jirajine
        8
    Jirajine  
       2020 年 6 月 1 日 via Android
    annotation 类似卫生宏吧,这种需求应该没问题才对。
    asanelder
        9
    asanelder  
    OP
       2020 年 6 月 1 日
    @fantastM 是这个处理器
    @Jrue0011 看你的思路,是想在 abstractprocessor 中,想办法得到源文件的路径,然后通过读文件的文件来得到?
    @inwar 铁子,这个只是注解处理阶段,还没到打包呢,连 class 文件还没生成呢,只是处理源文件。

    我的意思是,有没有相关的 annotation api 可以得到 source code. 比如说 TypeElement 就已经表示源文件中的一个类型结构了,按道理来说,通过 TypeElement 就可以得到它所表示的结构信息,也就是相关的 souce code,但我找了半天,好像没有。
    asanelder
        10
    asanelder  
    OP
       2020 年 6 月 1 日
    @Jirajine #8 请明示,没看懂。。。
    Jirajine
        11
    Jirajine  
       2020 年 6 月 1 日 via Android
    @asanelder 又看了一下,我弄错了,annotation 只能存元数据,你可以把类当参数传给你的 annotation 。
    如果需要注入代码的话可以通过反射,参考这个 https://stackoverflow.com/questions/1079343/java-simple-technique-for-annotation-based-code-injection
    zengmingyang96
        12
    zengmingyang96  
       2020 年 6 月 2 日
    用构建工具来做这件事情或许更好
    asanelder
        13
    asanelder  
    OP
       2020 年 6 月 2 日
    @zengmingyang96 #12 嗯,应该是另一种思路,只是最近突然想起 annotation,正好有一个小需求,就练习一下下
    wangyanrui
        14
    wangyanrui  
       2020 年 6 月 2 日
    抄一下 Lombok 应该可以的吧
    guyeu
        15
    guyeu  
       2020 年 6 月 2 日
    原始需求是啥呢。。如果你发现一种实现很别扭,或许可以重新考虑下需求。
    gaius
        16
    gaius  
       2020 年 6 月 2 日 via Android
    读源码不得读 java 文件吗,要么反编译 class 。。不知道你想干什么,如果是增强类可以用 cglib 之类的
    strawberryBug
        17
    strawberryBug  
       2020 年 6 月 2 日
    注解都是要设定 @Target 的,仅能拿到 Target 支持的类型(枚举类)
    asanelder
        18
    asanelder  
    OP
       2020 年 6 月 2 日
    @guyeu #15
    @gaius #16
    我的需求就是想根据被注解的 java 源文件生成 markdown 文件 ,而生成的 markdown 文件中,需要 java 源文件中的代码
    guyeu
        19
    guyeu  
       2020 年 6 月 2 日
    @asanelder #18 openjdk 或者说 javac 没有内置这样的功能,据我所知,也没有一个使用广泛的工具可以实现这样的功能。或许可以通过代码的合理组织,结合 asciidoc 这样可以包含其他文本文件的标记语言,实现类似的效果。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1193 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 60ms UTC 17:52 PVG 01:52 LAX 10:52 JFK 13:52
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86