开发者

Using Java Annotations - Generating Code

I'm using java 6 annotation processing api. I have followed the following excellent tutorial for creating an annotation processor that displays a message at build-time:

http://kerebus.com/2011/02/using-java-6-processors-in-eclipse/

However, in my case, I have a simple class as such:

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

@Retention(RetentionPolicy.RUNTIME)
@Target(value = ElementType.METHOD)
public @interface Criteria {
    String id();
    double width();
    double height();
}

As you can see, the aforementioned annotation is made available to the JVM at runtime using the meta-annotation 'Retention'. I use this 'Criteria' annotation in the source code of another class to annotate a method, like so:

@Criteria(id = "fooBar", 
    width = 22, 
    height = 10
)
public void fooStream() {       
    System.out.println("foo stream method");
} 

At runtime, I want to include the 'fooStream' method in another class, ONLY if variables that are passed in match the values of the elements in the @Criteria annotation, namely 'width' and 'height'. My question is, how could I take the method 'fooStream' and inject this into another class at run-time? Is this even possible? I'm not looking for any code examples, just answers to the two aforementioned questions. Also, in the link at the top, there is an example of generating a code using 'Ja开发者_开发知识库vaFileObject' and 'Writer' instances, where the generated code is passed as a string.


I don't believe Java supports runtime type mutation, meaning to modify the members on a given class you'd have to drop back to a compile time preprocessor or to a bytecode modification scheme.

I'd be able to point you in a better direction if I understood the "why" behind this question, but in the mean time, dynamic proxy classes might get you to where you want to be (JavaWorld article).

From the documentation:

A dynamic proxy class is a class that implements a list of interfaces specified at runtime such that a method invocation through one of the interfaces on an instance of the class will be encoded and dispatched to another object through a uniform interface. Thus, a dynamic proxy class can be used to create a type-safe proxy object for a list of interfaces without requiring pre-generation of the proxy class, such as with compile-time tools. Method invocations on an instance of a dynamic proxy class are dispatched to a single method in the instance's invocation handler, and they are encoded with a java.lang.reflect.Method object identifying the method that was invoked and an array of type Object containing the arguments.

Here's a decent tutorial on using Spring to inject dynamic proxies based on custom annotations. I think this is probably closest to the behavior you're after.


If you want runtime modification of you classes, you can use your own classloader and intercept loading of classes, introspect what you want and generate new bytecode using asm library instead of original classes. It is not very tricky, but you must be sure you need exactly that.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜