Class ReflectionAnnotations

java.lang.Object
io.micronaut.reflection.ReflectionAnnotations

public final class ReflectionAnnotations extends Object
Builds AnnotationMetadata and AnnotationValues from the annotations read reflectively from an AnnotatedElement, in the shape the annotation processors give the metadata they generate at compilation time.

Code written against generated metadata then works unchanged for an element that has none:

  • the meta-annotations of an annotation are its stereotypes, recursively, with their values;
  • a repeatable annotation is filed under its container, whether it was written once, several times or inside the container, and the container is registered so that AnnotationMetadata.getAnnotationValuesByType(Class) finds it;
  • the defaults of the members are registered and reachable through AnnotationMetadata.getDefaultValues(String) and the value accessors;
  • a class value is an AnnotationClassValue, an enum value is its name, a nested annotation is an AnnotationValue;
  • the members annotated NonBinding are recorded, so that a qualifier built from the metadata ignores them;
  • an annotation a class inherits through Inherited is present but not declared, from a super class as from an interface of its hierarchy, which the processors walk and Class.getAnnotations() leaves out.

An annotation instance does not say which members were written, so a member whose value equals its default is not part of the values of the annotation; it is served by the defaults, as a member that was not written is at compilation time.

The annotation mappers, transformers and remappers of the annotation processors are not applied: they are part of micronaut-core-processor and are not on a runtime classpath. The ReflectionAnnotationCustomizer services are their runtime counterpart, and receive the values of every annotation this class converts.

Since:
5.2.0
Author:
Denis Stepanov
  • Method Details

    • metadataOf

      public static AnnotationMetadata metadataOf(AnnotatedElement element)
      Builds the metadata of an element.
      Parameters:
      element - The element
      Returns:
      The metadata, AnnotationMetadata.EMPTY_METADATA when the element has no annotation
    • metadataOf

      public static AnnotationMetadata metadataOf(@Nullable AnnotatedElement... elements)
      Builds the metadata of several elements merged, the first element first: the field, the getter and the setter of a property, or a parameter and its type.
      Parameters:
      elements - The elements, a null element skipped
      Returns:
      The metadata, AnnotationMetadata.EMPTY_METADATA when none of the elements has an annotation
    • metadataOf

      public static AnnotationMetadata metadataOf(Annotation... annotations)
      Builds the metadata of annotation instances, each declared: the annotations a specification API hands over as an array, such as the ones of a JAX-RS entity or the qualifiers of a CDI lookup.
      Parameters:
      annotations - The annotations
      Returns:
      The metadata, AnnotationMetadata.EMPTY_METADATA when there is no annotation
    • declaring

      public static AnnotationMetadata declaring(Class<? extends Annotation> annotationType, Map<CharSequence, Object> values)
      The metadata of an element that declares an annotation type, without an instance of it: the annotation with the values given, its defaults and its stereotypes, as the processors record it.

      Code that adapts another container - a Guice binding annotation, a Spring bean marked primary - knows the annotation type and the members it means, and has no instance to read. Declaring the annotation by name alone loses its defaults and its stereotypes, and a qualifier built from such metadata then fails to match one built from the generated metadata of a bean.

      Parameters:
      annotationType - The annotation type, filed under its container when it is repeatable
      values - The values of the members, empty when the annotation is written bare
      Returns:
      The metadata
    • declaring

      public static AnnotationMetadata declaring(Class<? extends Annotation> annotationType)
      The metadata of an element that declares an annotation type with the defaults of its members.
      Parameters:
      annotationType - The annotation type
      Returns:
      The metadata
      See Also:
    • declare

      public static void declare(MutableAnnotationMetadata metadata, Class<? extends Annotation> annotationType, Map<CharSequence, Object> values)
      Adds an annotation type, the values given, its defaults and its stereotypes to a metadata under construction.
      Parameters:
      metadata - The metadata
      annotationType - The annotation type
      values - The values of the members, empty when the annotation is written bare
      See Also:
    • merge

      public static AnnotationMetadata merge(AnnotationMetadata first, AnnotationMetadata second)
      The annotations of two metadata in one, both declared: the metadata of a class together with the annotations another container means it to carry.

      A container adapting another one - a Spring bean it marks primary, a Guice binding it qualifies - has annotations of its own to add to the ones a class declares. Replacing the metadata of the class loses what the class says; a hierarchy keeps both but only the last level counts as declared, and the framework reads a scope, a qualifier and a primary marker from the declared level. This merges them, so both are declared.

      Parameters:
      first - The metadata whose values win where both declare the same annotation
      second - The metadata to add
      Returns:
      The merged metadata
    • add

      public static void add(MutableAnnotationMetadata metadata, AnnotatedElement element)
      Adds the annotations of an element to a metadata under construction. An annotation whose values cannot be read is left out, with a message logged at debug level: the generated metadata of an element records it, and the element must not lose the annotations that can be read because of it.
      Parameters:
      metadata - The metadata
      element - The element
    • add

      public static void add(MutableAnnotationMetadata metadata, Annotation annotation, boolean declared)
      Adds one annotation instance to a metadata under construction, as add(MutableAnnotationMetadata, AnnotatedElement) adds every annotation of an element: a caller keeping only some annotations of an element - the constraints, the qualifiers - filters the instances and adds the ones it keeps.
      Parameters:
      metadata - The metadata
      annotation - The annotation
      declared - Whether the annotation is declared on the element rather than inherited
    • contained

      public static List<Annotation> contained(Annotation annotation)
      The annotations a repeatable container holds.
      Parameters:
      annotation - The annotation
      Returns:
      The contained annotations, empty when the annotation is not the container of a repeatable annotation
    • values

      public static Map<CharSequence, Object> values(Annotation annotation)
      The values of the members of an annotation, as the metadata stores them: the members whose value is the default of the member are left out, a class is an AnnotationClassValue, an enum constant is its name, a nested annotation is an AnnotationValue and the members annotated NonBinding are listed under AnnotationUtil.NON_BINDING_ATTRIBUTE.

      A nested annotation is given the same treatment as the annotation holding it, recursively, and an array value is a copy the caller owns.

      Parameters:
      annotation - The annotation
      Returns:
      The values, mutable
      Throws:
      IllegalStateException - When a member of the annotation cannot be read
    • defaultValues

      public static Map<CharSequence, Object> defaultValues(Class<? extends Annotation> annotationType)
      The defaults of the members of an annotation type, in the shapes values(Annotation) gives the values.
      Parameters:
      annotationType - The annotation type
      Returns:
      The defaults, unmodifiable
    • valueOf

      public static <A extends Annotation> AnnotationValue<A> valueOf(A annotation)
      The annotation value of an annotation instance, carrying its defaults. An instance that is an AnnotationValueProvider - a synthetic annotation built from a value - returns that value.
      Type Parameters:
      A - The annotation type
      Parameters:
      annotation - The annotation
      Returns:
      The annotation value
    • valueOf

      public static <A extends Annotation> AnnotationValue<A> valueOf(A annotation, @Nullable Consumer<Map<CharSequence, Object>> customizer)
      The annotation value of an annotation instance, carrying its defaults, with its values customized.
      Type Parameters:
      A - The annotation type
      Parameters:
      annotation - The annotation
      customizer - The customizer of the values, receiving a mutable copy, can be null
      Returns:
      The annotation value
    • synthesize

      public static <A extends Annotation> A synthesize(Class<A> annotationType, AnnotationValue<A> annotationValue)
      Builds an annotation instance from an annotation value: the reverse of valueOf(Annotation). The instance implements AnnotationValueProvider, so that converting it back yields the value it was built from, and its members are the values of the annotation value completed by the defaults of the type.
      Type Parameters:
      A - The annotation type
      Parameters:
      annotationType - The annotation type
      annotationValue - The annotation value
      Returns:
      The annotation
    • synthesize

      public static <A extends Annotation> A synthesize(AnnotationValue<A> annotationValue, ClassLoader classLoader)
      Builds an annotation instance from an annotation value, the type resolved by name through a class loader.
      Type Parameters:
      A - The annotation type
      Parameters:
      annotationValue - The annotation value
      classLoader - The class loader defining the annotation type
      Returns:
      The annotation
      Throws:
      IllegalArgumentException - When the class loader does not define the annotation type