Adding programmatic annotations to a Java class

不羁岁月 提交于 2019-12-10 04:10:07

问题


Usage example:
I want to put on class fields a custom annotation @MyContainer and then add automatically on all such fields relevant Hibernate annotations (depending on field type and properties).
In additional I need to add JAXB XmlType annotation to the class and base the type name on the class name.
I would want additionally to add annotations to fields based on thier types, etc. All added annotations should be available at run time (So hibernate / JAXB can find them).
I'm aware of the following options:

  1. Pre-processing class source (bad option)
  2. Processing during compilation with javax.annotation.processing APIs
  3. Post compilation manipulation with tools such as Java Assist
  4. Manipulation during class loading with java.lang.instrument APIs
  5. Doing it with AspectJ (not powerful enough)

My primary goals are:

  1. Keep sync between class and source for debugging
  2. Support working from both Maven and IDE (Eclipse / Intellij)

I'll appreciate if people who already done such things can recommend the best approach for such a task (and perhaps potential pitfalls).


回答1:


Here is a code example for defining custom annotation. This @TesterInfo is applied on class level, store the tester details. This shows the different use of return types – enum, array and string.

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";

}



回答2:


I think pre-processing class sources should be your preferred way. This enables you to have your sources in sync with the compiled classes, which is good for debugging as you mentioned. But it is also good for version control, since you are able to check in those generated annotations. It is also a lot more difficult to track down problems in your tool, if it is run it during compilation. IDE support should also be no problem when running your code generation in the generate-sources phase.

Edit: Quick searching yielded some infos about programmatic java source modification using the eclipse jdt or some thing in netbeans. But this might be worth some more research or a question of its own.




回答3:


I want to suggest another approach on that. As my first answer might involve coding an own tool, you could also try a much simpler solution. As I hope you are unit testing your classes, you could implement a base class for every unit test of such a class. In this base class there is a test method, which checks that every field annotated with @MyContainer also has the required hibernate annotations.

We basically did the same thing, not for annotations but for serializability of fields and ran quite well with that approach.




回答4:


To have it work most transparent in IDE, command line build and at run-time, option 1 (using APT) and option 5 (using AspectJ) will give you best fit.

For option 1 you'll have to implement your own annotation processor that will inject additional annotations based on the presence of your own @MyContainer annotation. Here is an example of this approach used for something similar.

For option 5 you can simply use annotation declaration. Something like this:

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

Spring's Roo tool is extensively using option 5 and I certainly can't say it is not powerful enough.




回答5:


There are few alternatives as mentioned above and each have its upsides and downsides. That's why I don't think there a real "right" answer for the above question. My purpose was to get inputs from the community and from people who had done such things in the past and have experience. Personally I've chosen to use the Instrument API with Javassist. This way the classes are extended on run time (although the same tool can be used for post compile processing). The nice thing is that the agent can be loaded from inside the JVM which avoids handling all the command lines. It will be great to hear on other alternatives.
Thanks,
Avner



来源:https://stackoverflow.com/questions/11598333/adding-programmatic-annotations-to-a-java-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!