How @Target(ElementType.ANNOTATION_TYPE) works
Java annotations are marked with a @Target
annotation to declare possible joinpoints which can be decorated by that annotation. Values TYPE
, FIELD
, METHOD
, etc. of the ElementType
enum are clear and simply understandable.
Question
WHY to use @Target(ANNOTATION_TYPE)
value? What are the annotated annotations good for? What is their contribution? Give me an explanation of an idea how it works and why I should use it. Some already existing and well-known example of its usage would be great too.
You can use an annotated annotation to create a meta-annotation, for example consider this usage of @Transactional
in Spring:
/**
* Shortcut and more descriptive "alias" for {@code @Transactional(propagation = Propagation.MANDATORY)}.
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional(propagation = Propagation.MANDATORY)
public @interface RequiresExistingTransaction {
}
When you enable Spring to process the @Transactional
annotation, it will look for classes and methods that carry @Transactional
or any meta-annotation of it (an annotation that is annotated with @Transactional
).
Anyway this was just one concrete example how one can make use of an annotated annotation. I guess it's mostly frameworks like Spring where it makes sense to use them.
Each annotation annotated by @Target(ElementType.ANNOTATION_TYPE)
is called Meta-annotation
. That means, you can define your own custom annotations that are an amalgamation of many annotations combined into one annotation to create composed annotations
.
A good example from Android world is StringDef
Denotes that the annotated String element, represents a logical type and that its value should be one of the explicitly named constants.
@Retention(SOURCE) @StringDef({POWER_SERVICE, WINDOW_SERVICE, LAYOUT_INFLATER_SERVICE}) public @interface ServicesName {} public static final String POWER_SERVICE = "power"; public static final String WINDOW_SERVICE = "window"; public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
Code inspector will treat @ServicesName
and @WeekDays
in the same way as @StringDef
.
As a result we can create as much named StringDef
's as we need and override set of constants. @Target(ElementType.ANNOTATION_TYPE)
it is a tool that allows to extend the use of annotations.