Annotation Interface Retainable
Marks an annotation as retainable: every annotation that composes it keeps the composed occurrence on its own
AnnotationValue, in the AnnotationMetadata of every element the composing annotation is applied
to, in addition to flattening it into the element's stereotypes.
AnnotationMetadata indexes stereotypes by name, which loses the association between an individual
stereotype occurrence and the annotation that introduced it: two annotations that each compose a repeatable
annotation contribute two indistinguishable occurrences. A retainable annotation is also kept as a tree under
the annotation composing it, with member overrides declared through
io.micronaut.context.annotation.AliasFor already applied, and is read back with
AnnotationValue.getStereotypes(). An annotation is retainable when this marker is present anywhere in
its own stereotypes, so a framework annotation marks its whole family at once, and a retained occurrence keeps
its own retainable stereotypes in turn:
@Retainable
@interface Constraint {
}
@Constraint
@interface Size {
int min() default 0;
}
@Size(min = 5)
@interface Username {
@AliasFor(annotation = Size.class, member = "min")
int min() default 5;
}
// for an element annotated @Username(min = 3)
metadata.getAnnotation(Username.class).getStereotypes(); // [ @Size(min = 3) ]
Retention costs generated code proportional to the number of retainable occurrences at every use site, so it is opt-in and has no cost for annotations that compose nothing retainable. The marker itself is never retained.
- Since:
- 5.2.0