Adding Code to an Annotation
Sometimes you have a framework you would like to be able to add custom
annotations to. The problem is; how do you define what this custom
annotation does. A possible solution is to use a nested enum.
Published at DZone with permission of Peter Lawrey, author and DZone MVB. (source)Nested types
You can nest an interface, a class, an annotation or an enum inside any of these types. e.g.public class A {
public interface B {
public enum C {;
public @interface D {
public class E {
// etc etc
}
}
}
}
}
But is this useful or just a novelty?
Adding functionality to an annotation
You can define an interface the framework can call to determine how your custom annotation should behave.import java.lang.reflect.Member;
/**
* @author peter.lawrey
*/
public interface AnnotationHandler<A> {
void process(Model model, Member member, A annotation);
}
One way of associating the implementation with the annotation itself is
to provide a Singleton enum which implements this interface.
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Member;
/**
* @author peter.lawrey
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {
public int value() default 0;
enum HandlesAnnotation implements AnnotationHandler<CustomAnnotation> {
INSTANCE;
@Override
public void process(Model model, Member member, CustomAnnotation ca) {
// do something with a model based on the members details and the annotation state.
}
}
}
If an annotation could be handled a number of different ways (depending
on what process you are performing), you could provide more than one
implementation.
Using this approach, a framework which uses annotations can allow
developers to add custom annotations is a simple manner. The framework
can also make it clear how an annotation behaves, making it easier to
create annotations which are similar but need to be different in some
way.
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)
Tags:






Comments
Nicolas Frankel replied on Thu, 2012/03/15 - 5:10am
IMHO, annotations are markers; they shouldn't provide any behavior intrisiquely: on the contrary, annotations should be hints for code to manage the annotated class in a different way.
In this light, while annotations stay the same, different codes would manage the annotated class differently.
Ronald Miura replied on Thu, 2012/03/15 - 7:10am
in response to:
Nicolas Frankel
@Nicolas
Enums are typed integer constants, and may be used just like that. But they are also objects, that can have their own methods and attributes. One can use them to create state machines, a simple way to define a set of behaviors (without resorting to lots of ugly switch statements), and Joshua Bloch suggests its use as the simplest way to create serialization-safe singletons (http://java.sun.com/developer/technicalArticles/Interviews/bloch_effective_08_qa.html).
I've never thought about adding code to annotations, but it may be useful in some situations (altough, as anything, it could be badly used, of course). A common approach is to pass a class, which have the code, as a parameter to the annotation (EJB3 interceptors, JSR-303 validators, etc.), which isn't that different anyway.
When (not that long ago) EJB still required interfaces for everything, and you wanted to have only one implementation of some service (which is the most common), a simple way to keep interface and implementation close together was to make the implementation class a static inner class of the interface. Many would say this is a deadly sin and I should burn in Hell, but well, it was very useful, and the code was easier to maintain than to have different classes (or different packages, as some will always preach).
"Nothing is true, everything is permitted" :)