向Java类添加编程注释

7
使用示例:
我想在类字段上放置自定义注释@MyContainer,然后根据字段类型和属性自动添加所有相关的Hibernate注释。
此外,我需要向类添加JAXB XmlType注释,并将类型名称基于类名。
我还想根据它们的类型向字段添加注释等。 所有添加的注释应在运行时可用(因此Hibernate/JAXB可以找到它们)。
我知道以下选项:

  1. 预处理类源代码(不好的选择)
  2. 使用javax.annotation.processing API进行编译期处理
  3. 使用Java Assist等工具进行编译后操作
  4. 使用java.lang.instrument API在类加载时进行操作
  5. 使用AspectJ(功能不够强大)

我的主要目标是:

  1. 保持调试时类和源代码的同步
  2. 支持从Maven和IDE(Eclipse/Intellij)中进行操作

如果已经完成此类任务的人能够推荐最佳方法(以及可能存在的风险),我将不胜感激。


不生成注释,而是生成可以由Hibernate配置加载的Hibernate映射XML文件(hbm.xml),这个怎么样? - Strelok
谢谢,这是个好主意,但在我的情况下我更喜欢注解选项,因为我需要生成JAXB注解(也许将来还有其他注解)。 - Avner Levy
5个回答

1
这是一个定义自定义注释的代码示例。@TesterInfo应用在类级别上,存储测试人员的详细信息。它展示了不同返回类型的用法 - 枚举、数组和字符串。
package com.mkyong.test.core;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) //on class level
public @interface TesterInfo {

    public enum Priority {
       LOW, MEDIUM, HIGH
    }

    Priority priority() default Priority.MEDIUM;

    String[] tags() default "";

    String createdBy() default "Mkyong";

    String lastModified() default "03/01/2014";

}

0
为了使它在IDE、命令行构建和运行时最透明,选项1(使用APT)和选项5(使用AspectJ)会给你最合适的解决方案。
对于选项1,您将需要实现自己的注解处理器,根据您自己的@MyContainer注解的存在注入附加注解。这是这种方法的一个示例,用于类似something similar的情况。
对于选项5,您可以简单地使用注解声明。像这样:
declare @field : * ((@*..MyContainer *)).*(..) : @OtherAnnotation();

Spring的Roo工具广泛使用选项5,我肯定不能说它不够强大。


你能否基于类/方法/成员信息来设置注解和注解参数?例如,我需要检查容器数据类型并在几个可能的Hibernate注解之间进行选择。此外,我还需要根据字段名称生成Hibernate注解的列名等... - Avner Levy

0

我认为预处理类源代码应该是您首选的方式。这样可以使您的源代码与编译后的类保持同步,这对于调试非常有用,正如您所提到的。但是,这也有利于版本控制,因为您可以检查生成的注释。如果在编译期间运行工具,则更难跟踪工具中的问题。当在generate-sources阶段运行代码生成时,IDE支持也不应该成为问题。

编辑: 快速搜索得出一些关于程序化Java源代码修改的信息使用Eclipse JDTNetBeans中的某些内容。但这可能值得进一步研究或提出自己的问题。


谢谢您的回答。您能否提供更多关于解决方案的信息,例如可以使用哪些工具来分析源代码并操作它?缺点是源代码会填充低级注释,不够清晰(我考虑只为运行时添加注释)。 - Avner Levy
如果您担心这可能导致代码不干净,请考虑使用当前类的接口,并尽可能使用注释隐藏实现。 - SpaceTrucker

0

我想提供另一种方法。由于我的first answer可能涉及编写自己的工具,您也可以尝试一个更简单的解决方案。因为我希望您正在对类进行单元测试,所以您可以为每个此类单元测试实现一个基类。在这个基类中,有一个测试方法,它检查每个用@MyContainer注释的字段是否还具有必需的Hibernate注释。

我们基本上做了同样的事情,不是针对注释,而是针对字段的可序列化性,并且使用该方法运行得很好。


0

如上所述,有几种替代方案,每种都有其优缺点。这就是为什么我认为对于上述问题没有真正的“正确”答案。我的目的是从社区和过去做过这样事情并具有经验的人那里获得输入。个人而言,我选择使用Instrument API与Javassist。这样,类在运行时被扩展(尽管同样的工具也可以用于后编译处理)。好处是代理可以从JVM内部加载,避免了处理所有命令行的麻烦。很高兴听到其他替代方案。
谢谢,
Avner


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接