V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiangyuecn
V2EX  ›  Java

伸手: Java 有没有哪个注解可以在编译时插入当前时间,我想在代码里直接得到编译时间🤔

  •  1
     
  •   xiangyuecn ·
    xiangyuecn · 2023-04-09 14:22:32 +08:00 · 4104 次点击
    这是一个创建于 602 天前的主题,其中的信息可能已经有所发展或是发生改变。

    搜了半天没搜到,只有伸手了

    比如给类加上这个注解,会直接在类源码里面添加一个可以使用的静态字符串变量

    或者给一个字符串变量加上这个注解,编译时自动注入一个值


    不考虑使用配置文件 翻了翻 lombok ,似乎没有现成的,难不成要自己写一个编译期注解😂

    感觉这种需求挺多的吧,一个 class 文件里面自带了编译时间,能省不少事

    24 条回复    2023-04-10 19:05:04 +08:00
    sfc9982
        1
    sfc9982  
       2023-04-09 14:29:39 +08:00
    将编译时间保存在 Manifest 文件中,然后从代码中读取 Manifest 里的时间戳?
    learningman
        2
    learningman  
       2023-04-09 14:31:49 +08:00 via Android   ❤️ 1
    用 gradle 的话,写 task 在 build 之前 codegen 。
    挺多这种插件的,比如 buildKonfig
    Azzsanjin
        3
    Azzsanjin  
       2023-04-09 14:43:29 +08:00 via Android
    这应该和代码无关吧 得研究 jvm
    xiangyuecn
        4
    xiangyuecn  
    OP
       2023-04-09 14:50:59 +08:00
    @Azzsanjin 参考 lombok.extern.slf4j.Slf4j ,给类注解 @Slf4j 后,编译时会往代码里插入 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(XXX.class)

    实现一个编译期插入 public static final String BuildTime="2023-04-09 14:49:51" 类似的注解应该是可行的吧
    diagnostics
        5
    diagnostics  
       2023-04-09 14:57:09 +08:00
    bytebuddy ,asm ,javassist ,看 CTW 就可以了,一般是改字节码
    xiangyuecn
        6
    xiangyuecn  
    OP
       2023-04-09 15:04:02 +08:00
    @diagnostics 太难了 学不动😂
    forgottencoast
        7
    forgottencoast  
       2023-04-09 15:22:11 +08:00
    自己写个脚本,生成时间戳文件,编译的时候顺带执行这个脚本。
    这个应该比较容易实现吧。
    Achieve7
        8
    Achieve7  
       2023-04-09 15:51:30 +08:00
    一般都是 字节码织入, 比如 asm javasssist. 可以看一下 spring-aop 的源码, 写的挺详细的
    ychost
        9
    ychost  
       2023-04-09 15:54:03 +08:00
    Maven 插件搞一个就行了,别去卷 java APT 了,用 maven 插件或者 Gradle 插件更简洁,更快
    someonedeng
        10
    someonedeng  
       2023-04-09 16:29:41 +08:00
    编译的时候脚本 sed 一下代码 改一下不就得了
    weofuh
        11
    weofuh  
       2023-04-09 18:25:25 +08:00
    如果只是修改一个源码文件里的某个变量,如:string version = "1.0" maven 编译时设置一个新的版本号 version = “1.1” ,那可以用 replacer 插件来实现,比如 com.google.code.maven-replacer-plugin:replacer
    zhady009
        12
    zhady009  
       2023-04-09 18:38:14 +08:00
    换个思路不要直接注入进 JVM 内部,从外部文件读取就好了
    如果是 SpringBoot 项目可以读 build-info.properties
    williamx
        13
    williamx  
       2023-04-09 18:50:31 +08:00
    @someonedeng +1 ,反正要写编译脚本,直接 sed 修改,懒得去研究各种编译框架。
    ingxx
        14
    ingxx  
       2023-04-09 18:52:05 +08:00
    JSR269 编译时修改语法树试试呢
    MakHoCheung
        15
    MakHoCheung  
       2023-04-09 18:54:49 +08:00
    Java 的 Annotation Processing Tool
    k9982874
        16
    k9982874  
       2023-04-09 19:03:20 +08:00 via Android   ❤️ 2
    源码里面 public final String compileDate = "{COMPILE_DATE}";
    maven 或 gradle 编译前执行 sed 替换指定文件里的{COMPILE_DATE},编译结束替换回{COMPILE_DATE}简单粗暴
    OldCarMan
        17
    OldCarMan  
       2023-04-10 04:40:42 +08:00
    编译过程是分几个阶段的,明确你要的是哪个阶段的时间,参考你发的 4 楼信息,个人觉得你要的是一个成员变量的默认值,如果是的话,lombok 的 @Builder.Default
    @Builder.Default
    private LocalDate buildTime=LocalDate.now();
    可能适合你,当然你也可以利用 Pluggable Annotation Processing API ,参照 lombok 实现原理自己写一个注解
    ic3z
        18
    ic3z  
       2023-04-10 09:53:48 +08:00 via iPhone
    Java 没有内置的注解可以在编译时插入当前时间。不过,你可以使用自定义注解和 Java 的注解处理器来实现这个功能。具体实现方式可以参考一些第三方库,例如:Maven 插件 "buildnumber-maven-plugin" 或 Gradle 插件 "gradle-buildinfo-plugin"。来自 gpt
    vvtf
        19
    vvtf  
       2023-04-10 10:00:07 +08:00
    这不就是 jsr269 的东西吗?
    我们的定制化需求就是靠这个实现的.
    你这个增加代码的需求就几行代码就搞定.
    whatiam
        20
    whatiam  
       2023-04-10 10:57:27 +08:00
    这个我有个简单的实践方式,并且已经用了好久了:用 gradle ,建立一个 task 依赖于 build ,然后生成 yaml 文件,也一同打包。这个 yaml 里面包含各种信息,比如分支名,commit id ,commit message ,build time ,编译环境的 IP 等。然后进一步的,可以用一个通用接口来获取这些信息。这些信息蛮有用的,可以用于校验应用版本依赖,也可以方便看问题。
    cyningxu
        21
    cyningxu  
       2023-04-10 13:50:19 +08:00
    gradle 插件或加任务不行吗?
    bv
        22
    bv  
       2023-04-10 14:00:55 +08:00
    如果你是 Spring Boot 项目,用的又是 Maven 管理。可以使用 @@ 表达式的。
    在配置文件中加入以下配置,编译时 @maven.build.timestamp@ 就会被替换为编译时的时间:
    ```
    [email protected]@
    ```
    xiangyuecn
        23
    xiangyuecn  
    OP
       2023-04-10 16:28:08 +08:00
    @sfc9982 @learningman @Azzsanjin @diagnostics @forgottencoast @Achieve7 @ychost @someonedeng @weofuh @zhady009 @williamx @ingxx @MakHoCheung @k9982874 @OldCarMan @ic3z @vvtf @vvtf @whatiam @cyningxu @bv

    感谢大家提供的思路💖,应该是不容易找到现成的注解去使用,自己实现一个注解处理器也麻烦,最优的解决办法应该还是用插件或脚本直接替换源码(从始至终就没考虑使用配置文件,用配置文件就不发帖了)

    我这用的是 Maven ,pom.xml 的 plugins 里面加了 org.codehaus.mojo:exec-maven-plugin:3.1.0 插件,打包时直接调用 java 命令执行项目里的一个类的 main 函数,我在这个函数里面自己写代码进行任意的修改

    pom.xml 的配置:
    <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>3.1.0</version>
    <executions>
    <execution>
    <phase>compile</phase>
    <goals>
    <goal>java</goal>
    </goals>
    </execution>
    </executions>
    <configuration>
    <mainClass>com.MyJavaCompile</mainClass>
    <arguments>
    <argument>sourceDirectory=${project.build.sourceDirectory}</argument>
    <argument>outputDirectory=${project.build.outputDirectory}</argument>
    </arguments>
    </configuration>
    </plugin>

    会调用 MyJavaCompile.main ,由于这个是自己写的代码,自由度奇高😂
    GuuJiang
        24
    GuuJiang  
       2023-04-10 19:05:04 +08:00
    在 maven 的 goals 里加上 build-info ,如果你是 SpringBoot 项目的话直接注入一个 BuildProperties 对象就好了,通过这个对象就能取到构建时间、版本号等,不是 SpringBoot 项目的话就自己读取 manifest 文件
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2616 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 10:32 · PVG 18:32 · LAX 02:32 · JFK 05:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.