将编程注释添加到Java类

时间:2012-07-22 06:59:29

标签: java compiler-construction annotations bytecode-manipulation

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

  1. 预处理类源(错误选项)
  2. 使用javax.annotation.processing API编译期间的处理
  3. 使用Java Assist等工具进行编译后操作
  4. 使用java.lang.instrument API加载类时的操作
  5. 使用AspectJ(功能不够强大)
  6. 我的主要目标是:

    1. 在类和源之间保持同步以进行调试
    2. 支持Maven和IDE(Eclipse / Intellij)的工作
    3. 如果已经完成此类工作的人能够为这样的任务推荐最佳方法(也许是潜在的陷阱),我将不胜感激。

5 个答案:

答案 0 :(得分: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";

}

答案 1 :(得分:0)

我认为预处理类源应该是您的首选方式。这使您可以使源与已编译的类同步,这对于您提到的调试很有用。但它也适用于版本控制,因为您可以检入那些生成的注释。如果在编译期间运行它,那么跟踪工具中的问题也要困难得多。在generate-sources阶段运行代码生成时,IDE支持也应该没有问题。

编辑: 快速搜索产生了一些关于程序化java源代码修改的信息 using the eclipse jdtsome thing in netbeans。但这可能值得一些研究或自己的问题。

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

要让它在IDE,命令行构建和运行时最透明,选项1(使用APT)和选项5(使用AspectJ)将为您提供最佳选择。

对于选项1,您必须实现自己的注释处理器,该处理器将根据您自己的@MyContainer注释的存在注入其他注释。以下是something similar使用此方法的示例。

对于选项5,您只需使用annotation declaration即可。像这样:

declare @field : * ((@*..MyContainer *)).*(..) : @OtherAnnotation();

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

答案 4 :(得分:0)

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