Reputation: 197
I want to implement a custom annotation which when used by other classes exposes two methods to them. Something like shown below:
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface BaseEntity{
public String toString(){ return "Hello" ;}
public String toCustomString() { return "my hello";}
}
Now what I want is whenever any class uses the above annotation. It gets these methods exposed to it by default, something like what Lombok does when we use @Getter
@BaseEntity
public class Person{}
Person p = new Person();
p.toCustomString(); // this should work
Upvotes: 4
Views: 2315
Reputation: 1
There is one way of you some how manage to manipulate .class file with org.ow2.asm
Upvotes: 0
Reputation: 2026
While not exactly what you asked, I think you can achieve what you want with a class hierarchy that takes advantage of the annotation:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface BaseEntity {
String string();
String customString();
}
public abstract class AbstractClass {
@Override
public String toString() {
return getClass().getAnnotation(BaseEntity.class).string();
}
public String toCustomString() {
return getClass().getAnnotation(BaseEntity.class).customString();
}
}
And then a concrete subclass:
@BaseEntity(string = "Hello", customString = "my hello")
public class Example extends AbstractClass {
public static void main(String[] args) throws Exception {
Example example = new Example();
System.out.println(example.toString());
System.out.println(example.toCustomString());
}
}
yields:
Hello
my hello
In response to your comment, my real-world solution is to define an annotation and an interface with default methods (which makes a toString()
implementation problematic):
@BaseEntity(customString = "my hello")
public class Example implements BaseEntityAnnotated {
public static void main(String[] args) throws Exception {
Example example = new Example();
System.out.println(example.toCustomString());
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface BaseEntity {
String customString();
}
public interface BaseEntityAnnotated {
default String toCustomString() {
return this.getClass().getAnnotation(BaseEntity.class).customString();
}
}
I then implement a Processor
that enforces an entity annotated with BaseEntity
must also implement BaseEntityAnnotated
.
I have examples at AntTask
, AnnotatedAntTask.getAntTaskName()
, and AntTaskProcessor.
Upvotes: 2
Reputation: 879
You need to create an annotation processing class (which must be a subclass of javax.annotation.processing.AbstractProcessor
) to actually add the code into the Person
class.
See: http://hannesdorfmann.com/annotation-processing/annotationprocessing101
Upvotes: 1