Matthys Strydom
Matthys Strydom

Reputation:

Can annotations be used for code injection?

I realise that this might be a question that has been asked and answered, but please bear with me.

I want to know if it is possible to use annotations to inject code into your classes compile time. The classic example is to generate a getter and setter for the members of your object. This is not exactly what I need it for, but it serves to illustrate the basic idea.

Now on the internet the basic answer I get is no, but this guy did it:

link text

Does anyone know how he does what he does (and if he actually does what he says he does)?

The main thing is that he does not use an annotation processor to generate a new java file to compile. This technique I am aware of and will not work for our purpose.

Thanks

Upvotes: 10

Views: 3453

Answers (4)

McDowell
McDowell

Reputation: 108889

I went looking for something similar last year. There is no standard way to alter classes using annotation processors or the compiler and the annotation API documentation recommends creating decorators.

If you are willing to live with the hacks, have a look at Adrian Kuhn's use of the private API where he adds Roman numeral literals to Java. This approach is limited to the Sun javac compiler and you would need to implement something else if you used another (like the Eclipse compiler).


Edit: anyone interested in this area should check out Project Lombok.

Upvotes: 3

Scott Stanchfield
Scott Stanchfield

Reputation: 30642

You can do this, but you're not supposed to modify the class containing the annotations. (The trick you link to uses the compile tree api to modify the bytecode being generated...) This is not supported and will probably be guarded against in later Java SDKs.

The proper way to do it is to generate a superclass, subclass or wrapper class.

I've written a set of annotations that generate getters/setters and other fun stuff. I generate a superclass.

See http://code.google.com/p/javadude/wiki/Annotations

You can do things like

package sample;

import com.javadude.annotation.Bean;
import com.javadude.annotation.Property;
import com.javadude.annotation.PropertyKind;

@Bean(properties={
    @Property(name="name"),
    @Property(name="phone", bound=true),
    @Property(name="friend", type=Person.class, kind=PropertyKind.LIST)
}) 
public class Person extends PersonGen {
}

and it'll generate PersonGen for you with the fields/getters/setters and bound property support.

Upvotes: 2

pgras
pgras

Reputation: 12770

It is not supported to modify code at compile time but it seems to be possible by using non-supported javac-internal APIs, here is a post referencing the hanbuy-panno solution with also a link to the code...

Upvotes: 5

SteveD
SteveD

Reputation: 5405

Something needs to process the annotations, so it either happens at compile time with an annotation processor or at runtime with reflection (yes I know, there are even more exotic ways of doing it at runtime).

He most definitely is using an annotation processor, it's just that it's implicit. The javac command will search the class path for annotation processors if not explicitly set.

Since he uses this command to compile:

javac -cp ~/development/panno/build/hanhuy-panno.jar *.java

We see he has modified the class path to include the hanhuy-panno.jar, which will contain the annotation processor.

Why not just email the guy and ask if he'll give you the code?

Upvotes: 1

Related Questions