7

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

  1. 预处理类源(坏的选择)
  2. 处理编译期间javax.annotation.processing中的API
  3. 后编译操纵的工具,如Java类加载与java.lang.instrument中的API
  4. 使用AspectJ(不够强大)
否则它在帮助
  • 操纵

    我的主要目标是:

    1. 保留类和源极之间的同步进行调试
    2. 支持来自Maven和IDE(Eclipse中/的IntelliJ)工作

    ,我会很感激,如果谁的人已经做过这样的事情可以为这样的任务推荐最好的方法(也许是潜在的陷阱)。

  • +0

    怎么样不生成注释,而是生成可以通过休眠配置加载的hibernate映射XML文件(hbm.xml)? – Strelok 2012-07-22 14:08:20

    +0

    谢谢,这是一个好主意,但我更喜欢我的情况下的注释选项,因为我还需要生成JAXB注释(以及将来可能还有其他注解)。 – 2012-07-22 14:30:29

    回答

    0

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

    编辑: 快速搜索产生约程序的Java源修改 using the eclipse jdtsome thing in netbeans一些相关信息。但是,这可能值得更多的研究或自己的问题。

    +0

    感谢您的回答。您能否提供关于解决方案的更多信息,例如哪些工具可用于分析源代码并对其进行处理?不利的一面是源代码被低级别的注释填充,不太清晰(我想为运行时添加注释)。 – 2012-07-23 01:00:07

    +0

    如果您担心这会导致代码不干净,您应该考虑使用当前类的接口并尽可能使用注释隐藏实现。 – SpaceTrucker 2012-07-23 07:07:23

    0

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

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

    0

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

    对于选项1,您必须实现自己的注释处理器,该处理器将根据您自己的@MyContainer注释的存在注入其他注释。这是用于something similar的这种方法的一个例子。

    对于选项5,您可以简单地使用annotation declaration。这样的事情:

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

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

    +0

    您可以将注释和注释参数基于类/方法/成员信息吗?例如,我需要检查容器数据类型并选择几个可能的休眠注释。另外我需要为基于字段名称的hibernate注释生成列名称...... – 2012-07-25 06:19:07

    0

    上面提到的几种替代方案各有其优点和缺点。这就是为什么我不认为上述问题有真正的“正确”答案。我的目的是从社区和过去曾经做过这类事情并有过经验的人那里获得投入。就我个人而言,我选择使用带有Javassist的Instrument API。通过这种方式,类可以在运行时进行扩展(尽管可以使用相同的工具进行后期编译处理)。好处是代理可以从JVM内部加载,避免处理所有的命令行。能听到其他选择会很高兴。
    谢谢,
    Avner

    0

    以下是定义自定义注释的代码示例。这个@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"; 
    
    }