Class AnnotationProvider

java.lang.Object
org.apache.juneau.commons.reflect.AnnotationProvider

public class AnnotationProvider extends Object
Enhanced annotation provider that returns AnnotationInfo objects and supports runtime annotations.

This class provides a modern API for retrieving annotations with the following benefits:

  • Returns AnnotationInfo wrappers that provide additional methods and type safety
  • Supports filtering by annotation type using streams
  • Properly handles repeatable annotations
  • Searches up the class/method hierarchy with well-defined order of precedence
  • Supports runtime annotations (annotations added programmatically at runtime)
  • Caches results for performance
Annotation Order of Precedence:
For Classes (find(Class, ClassInfo, AnnotationTraversal...)):

Annotations are returned in child-to-parent order with the following precedence:

  1. Runtime annotations on the class (highest priority)
  2. Declared annotations on the class
  3. Runtime annotations on parent classes (child-to-parent order)
  4. Declared annotations on parent classes (child-to-parent order)
  5. Runtime annotations on interfaces (child-to-parent order)
  6. Declared annotations on interfaces (child-to-parent order)
  7. Declared annotations on the package (lowest priority)

// Example: Given class Child extends Parent // Annotation order will be: // 1. Runtime annotations on Child // 2. @Annotation on Child // 3. Runtime annotations on Parent // 4. @Annotation on Parent // 5. Runtime annotations on IChild (if Child implements IChild) // 6. @Annotation on IChild // 7. @Annotation on package-info.java

For Methods (find(Class, MethodInfo, AnnotationTraversal...)):

Annotations are returned in child-to-parent order with the following precedence:

  1. Runtime annotations on the method (highest priority)
  2. Declared annotations on the method
  3. Runtime annotations on overridden parent methods (child-to-parent order)
  4. Declared annotations on overridden parent methods (child-to-parent order)
For Fields (find(Class, FieldInfo, AnnotationTraversal...)):

Annotations are returned with the following precedence:

  1. Runtime annotations on the field (highest priority)
  2. Declared annotations on the field
For Constructors (find(Class, ConstructorInfo, AnnotationTraversal...)):

Annotations are returned with the following precedence:

  1. Runtime annotations on the constructor (highest priority)
  2. Declared annotations on the constructor
Runtime Annotations:

Runtime annotations are concrete objects that implement annotation interfaces, added programmatically via the builder's AnnotationProvider.Builder.addRuntimeAnnotations(List) method. They allow you to dynamically apply annotations to classes, methods, fields, and constructors at runtime without modifying source code.

How Runtime Annotations Work:

  • Runtime annotations are Java objects that implement annotation interfaces (e.g., @Bean)
  • They use special methods like on() or onClass() to specify their targets
  • They always take precedence over declared annotations at the same level
  • They are particularly useful for applying annotations to classes you don't control

// Example: Creating a runtime annotation Bean runtimeAnnotation = BeanAnnotation .create() .onClass(MyClass.class) // Target class .typeName("MyType") // Annotation property .build(); // Add to provider AnnotationProvider provider = AnnotationProvider .create() .addRuntimeAnnotations(runtimeAnnotation) .build(); // Now MyClass will be found with @Bean annotation Stream<AnnotationInfo<Bean>> annotations = provider.find(Bean.class, MyClass.class);

Targeting Methods:

  • on() - String array of fully-qualified names (e.g., "com.example.MyClass.myMethod")
  • onClass() - Class array for type-safe targeting

Runtime annotations are evaluated before declared annotations at each level, giving them higher priority. For example, a runtime @Bean annotation on a class will be found before any @Bean annotation declared directly on that class.

Comparison with ElementInfo Methods:

The methods in this class differ from ClassInfo.getAnnotations(), MethodInfo.getAnnotations(), etc.:

  • Runtime Annotations: ElementInfo methods return ONLY declared annotations. This class includes runtime annotations.
  • Hierarchy: ElementInfo methods may have different traversal logic. This class uses a consistent approach.
  • Precedence: Runtime annotations are inserted at each level with higher priority than declared annotations.
Usage:

// Create with default settings AnnotationProvider provider = AnnotationProvider.create().build(); // Create with runtime annotations AnnotationProvider provider = AnnotationProvider .create() .annotations(new MyAnnotationImpl()) .build(); // Find all annotations on a class List<AnnotationInfo<Annotation>> annotations = provider.find(MyClass.class); // Find specific annotation type on a class Stream<AnnotationInfo<MyAnnotation>> myAnnotations = provider.find(MyAnnotation.class, MyClass.class);

See Also:
  • Field Details

  • Constructor Details

  • Method Details

    • create

      Creates a new AnnotationProvider.Builder for constructing an annotation provider.
      Returns:
      A new builder for configuring the annotation provider.
    • find

      public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, ClassInfo c, AnnotationTraversal... traversals)
      Finds annotations from a class using configurable traversal options.

      This method provides a flexible API for traversing annotations. It uses AnnotationTraversal enums to configure what elements to search and in what order.

      Examples:

      // Search class only List<AnnotationInfo<MyAnnotation>> l1 = find(MyAnnotation.class, ci, SELF); // Search class and parents List<AnnotationInfo<MyAnnotation>> l2 = find(MyAnnotation.class, ci, SELF, PARENTS); // Search class, parents, and package (parent-first order using rstream) Stream<AnnotationInfo<MyAnnotation>> s3 = rstream(find(MyAnnotation.class, ci, SELF, PARENTS, PACKAGE));

      Type Parameters:
      A - The annotation type.
      Parameters:
      type - The annotation type to search for.
      c - The class to search.
      traversals - The traversal options (what to search and order).
      Returns:
      A list of AnnotationInfo objects. Never null.
    • find

      public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, ConstructorInfo c, AnnotationTraversal... traversals)
      Finds annotations from a constructor using configurable traversal options.

      This method provides a flexible, stream-based API for traversing constructor annotations without creating intermediate lists.

      Examples:

      // Search constructor annotations Stream<AnnotationInfo<MyAnnotation>> s1 = findAnnotations(MyAnnotation.class, ci, SELF);

      Type Parameters:
      A - The annotation type.
      Parameters:
      type - The annotation type to search for.
      c - The constructor to search.
      traversals - The traversal options.
      Returns:
      A list of AnnotationInfo objects. Never null.
    • find

      public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, FieldInfo f, AnnotationTraversal... traversals)
      Finds annotations from a field using configurable traversal options.

      This method provides a flexible, stream-based API for traversing field annotations without creating intermediate lists.

      Examples:

      // Search field annotations Stream<AnnotationInfo<MyAnnotation>> s1 = findAnnotations(MyAnnotation.class, fi, SELF);

      Type Parameters:
      A - The annotation type.
      Parameters:
      type - The annotation type to search for.
      f - The field to search.
      traversals - The traversal options.
      Returns:
      A list of AnnotationInfo objects. Never null.
    • find

      public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, MethodInfo m, AnnotationTraversal... traversals)
      Finds annotations from a method using configurable traversal options.

      This method provides a flexible API for traversing method annotations.

      Examples:

      // Search method and matching parent methods List<AnnotationInfo<MyAnnotation>> l1 = find(MyAnnotation.class, mi, SELF, MATCHING_METHODS); // Search method, matching methods, and return type (parent-first using rstream) Stream<AnnotationInfo<MyAnnotation>> s2 = rstream(find(MyAnnotation.class, mi, SELF, MATCHING_METHODS, RETURN_TYPE));

      Type Parameters:
      A - The annotation type.
      Parameters:
      type - The annotation type to search for.
      m - The method to search.
      traversals - The traversal options.
      Returns:
      A list of AnnotationInfo objects. Never null.
    • find

      public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, ParameterInfo p, AnnotationTraversal... traversals)
      Finds annotations from a parameter using configurable traversal options in child-to-parent order.

      This method provides a flexible, stream-based API for traversing parameter annotations without creating intermediate lists.

      Supported Traversal Types:
      • SELF - Annotations declared directly on this parameter
      • MATCHING_PARAMETERS - Matching parameters in parent methods/constructors (child-to-parent)
      • PARAMETER_TYPE - The parameter's type hierarchy (includes class parents and package)

      Default: If no traversals are specified, defaults to: SELF, MATCHING_PARAMETERS, PARAMETER_TYPE

      Examples:

      // Search parameter, matching parameters, and parameter type (child-to-parent) Stream<AnnotationInfo<MyAnnotation>> s1 = find(MyAnnotation.class, pi, SELF, MATCHING_PARAMETERS, PARAMETER_TYPE); // Just search this parameter Stream<AnnotationInfo<MyAnnotation>> s2 = find(MyAnnotation.class, pi, SELF); // Search in parent-to-child order using findTopDown Stream<AnnotationInfo<MyAnnotation>> s3 = findTopDown(MyAnnotation.class, pi, SELF, MATCHING_PARAMETERS, PARAMETER_TYPE);

      Type Parameters:
      A - The annotation type.
      Parameters:
      type - The annotation type to search for.
      p - The parameter to search.
      traversals - The traversal options. If not specified, defaults to SELF, MATCHING_PARAMETERS, PARAMETER_TYPE.
      Valid values: SELF, MATCHING_PARAMETERS, PARAMETER_TYPE
      Returns:
      A list of AnnotationInfo objects in child-to-parent order. Never null.
    • find

      public List<AnnotationInfo<? extends Annotation>> find(ClassInfo c, AnnotationTraversal... traversals)
      Finds all annotations from a class using configurable traversal options, without filtering by annotation type.

      This method provides a flexible API for traversing all class annotations. Unlike find(Class, ClassInfo, AnnotationTraversal...), this method does not filter by annotation type.

      Examples:

      // Get all annotations from class only List<AnnotationInfo<Annotation>> l1 = find(ci, SELF); // Get all annotations from class and parents List<AnnotationInfo<Annotation>> l2 = find(ci, SELF, PARENTS);

      Parameters:
      c - The class to search.
      traversals - The traversal options (what to search and order).
      Returns:
      A list of AnnotationInfo objects. Never null.
    • find

      public List<AnnotationInfo<? extends Annotation>> find(ConstructorInfo c, AnnotationTraversal... traversals)
      Finds all annotations from a constructor using configurable traversal options, without filtering by annotation type.

      This method provides a flexible, stream-based API for traversing all constructor annotations without creating intermediate lists. Unlike find(Class, ConstructorInfo, AnnotationTraversal...), this method does not filter by annotation type.

      Examples:

      // Get all annotations from constructor Stream<AnnotationInfo<Annotation>> s1 = find(ci, SELF);

      Parameters:
      c - The constructor to search.
      traversals - The traversal options.
      Returns:
      A list of AnnotationInfo objects. Never null.
    • find

      public List<AnnotationInfo<? extends Annotation>> find(FieldInfo f, AnnotationTraversal... traversals)
      Finds all annotations from a field using configurable traversal options, without filtering by annotation type.

      This method provides a flexible, stream-based API for traversing all field annotations without creating intermediate lists. Unlike find(Class, FieldInfo, AnnotationTraversal...), this method does not filter by annotation type.

      Examples:

      // Get all annotations from field Stream<AnnotationInfo<Annotation>> s1 = find(fi, SELF);

      Parameters:
      f - The field to search.
      traversals - The traversal options.
      Returns:
      A list of AnnotationInfo objects. Never null.
    • find

      public List<AnnotationInfo<? extends Annotation>> find(MethodInfo m, AnnotationTraversal... traversals)
      Finds all annotations from a method using configurable traversal options, without filtering by annotation type.

      This method provides a flexible API for traversing all method annotations. Unlike find(Class, MethodInfo, AnnotationTraversal...), this method does not filter by annotation type.

      Examples:

      // Get all annotations from method and matching parent methods List<AnnotationInfo<Annotation>> l1 = find(mi, SELF, MATCHING_METHODS); // Get all annotations from method, matching methods, and return type List<AnnotationInfo<Annotation>> l2 = find(mi, SELF, MATCHING_METHODS, RETURN_TYPE);

      Parameters:
      m - The method to search.
      traversals - The traversal options.
      Returns:
      A list of AnnotationInfo objects. Never null.
    • find

      public List<AnnotationInfo<? extends Annotation>> find(ParameterInfo p, AnnotationTraversal... traversals)
      Finds all annotations from a parameter using configurable traversal options, without filtering by annotation type.

      This method provides a flexible, stream-based API for traversing all parameter annotations without creating intermediate lists. Unlike find(Class, ParameterInfo, AnnotationTraversal...), this method does not filter by annotation type.

      Supported Traversal Types:
      • SELF - Annotations declared directly on this parameter
      • MATCHING_PARAMETERS - Matching parameters in parent methods/constructors (child-to-parent)
      • PARAMETER_TYPE - The parameter's type hierarchy (includes class parents and package)

      Default: If no traversals are specified, defaults to: SELF, MATCHING_PARAMETERS, PARAMETER_TYPE

      Examples:

      // Get all annotations from parameter, matching parameters, and parameter type Stream<AnnotationInfo<Annotation>> s1 = find(pi, SELF, MATCHING_PARAMETERS, PARAMETER_TYPE); // Just get annotations from this parameter Stream<AnnotationInfo<Annotation>> s2 = find(pi, SELF);

      Parameters:
      p - The parameter to search.
      traversals - The traversal options. If not specified, defaults to SELF, MATCHING_PARAMETERS, PARAMETER_TYPE.
      Valid values: SELF, MATCHING_PARAMETERS, PARAMETER_TYPE
      Returns:
      A list of AnnotationInfo objects in child-to-parent order. Never null.
    • has

      public <A extends Annotation> boolean has(Class<A> type, ClassInfo c, AnnotationTraversal... traversals)
      Checks if a class has the specified annotation.

      This is a convenience method equivalent to:

      find(type, clazz, traversals).findFirst().isPresent()

      Supported Traversal Types:
      • SELF - Annotations declared directly on this class
      • PARENTS - Parent classes and interfaces (child-to-parent order)
      • PACKAGE - The package annotations

      Default: If no traversals are specified, defaults to: PARENTS, PACKAGE
      Note: PARENTS includes the class itself plus all parent classes and interfaces.

      Example:

      // Check if class has @MyAnnotation anywhere in hierarchy boolean hasIt = has(MyAnnotation.class, ci); // Check only on the class itself boolean hasIt2 = has(MyAnnotation.class, ci, SELF);

      Type Parameters:
      A - The annotation type.
      Parameters:
      type - The annotation type to search for.
      c - The class to search.
      traversals - The traversal options. If not specified, defaults to SELF, PARENTS, PACKAGE.
      Valid values: SELF, PARENTS, PACKAGE
      Returns:
      true if the annotation is found, false otherwise.
    • has

      public <A extends Annotation> boolean has(Class<A> type, ConstructorInfo c, AnnotationTraversal... traversals)
      Checks if a constructor has the specified annotation.

      This is a convenience method equivalent to:

      find(type, constructor, traversals).findFirst().isPresent()

      Supported Traversal Types:
      • SELF - Annotations declared directly on this constructor

      Default: If no traversals are specified, defaults to: SELF

      Example:

      // Check if constructor has @MyAnnotation boolean hasIt = has(MyAnnotation.class, ci);

      Type Parameters:
      A - The annotation type.
      Parameters:
      type - The annotation type to search for.
      c - The constructor to search.
      traversals - The traversal options. If not specified, defaults to SELF.
      Valid values: SELF
      Returns:
      true if the annotation is found, false otherwise.
    • has

      public <A extends Annotation> boolean has(Class<A> type, FieldInfo f, AnnotationTraversal... traversals)
      Checks if a field has the specified annotation.

      This is a convenience method equivalent to:

      find(type, field, traversals).findFirst().isPresent()

      Supported Traversal Types:
      • SELF - Annotations declared directly on this field

      Default: If no traversals are specified, defaults to: SELF

      Example:

      // Check if field has @MyAnnotation boolean hasIt = has(MyAnnotation.class, fi);

      Type Parameters:
      A - The annotation type.
      Parameters:
      type - The annotation type to search for.
      f - The field to search.
      traversals - The traversal options. If not specified, defaults to SELF.
      Valid values: SELF
      Returns:
      true if the annotation is found, false otherwise.
    • has

      public <A extends Annotation> boolean has(Class<A> type, MethodInfo m, AnnotationTraversal... traversals)
      Checks if a method has the specified annotation.

      This is a convenience method equivalent to:

      find(type, method, traversals).findFirst().isPresent()

      Supported Traversal Types:
      • SELF - Annotations declared directly on this method
      • MATCHING_METHODS - Matching methods in parent classes (child-to-parent)
      • RETURN_TYPE - The return type hierarchy (includes class parents and package)
      • PACKAGE - The declaring class's package annotations

      Default: If no traversals are specified, defaults to: SELF, MATCHING_METHODS, RETURN_TYPE, PACKAGE

      Example:

      // Check if method has @MyAnnotation anywhere in hierarchy boolean hasIt = has(MyAnnotation.class, mi); // Check only on the method itself boolean hasIt2 = has(MyAnnotation.class, mi, SELF);

      Type Parameters:
      A - The annotation type.
      Parameters:
      type - The annotation type to search for.
      m - The method to search.
      traversals - The traversal options. If not specified, defaults to SELF, MATCHING_METHODS, RETURN_TYPE, PACKAGE.
      Valid values: SELF, MATCHING_METHODS, RETURN_TYPE, PACKAGE
      Returns:
      true if the annotation is found, false otherwise.
    • has

      public <A extends Annotation> boolean has(Class<A> type, ParameterInfo p, AnnotationTraversal... traversals)
      Checks if a parameter has the specified annotation.

      This is a convenience method equivalent to:

      find(type, parameter, traversals).findFirst().isPresent()

      Supported Traversal Types:
      • SELF - Annotations declared directly on this parameter
      • MATCHING_PARAMETERS - Matching parameters in parent methods/constructors (child-to-parent)
      • PARAMETER_TYPE - The parameter's type hierarchy (includes class parents and package)

      Default: If no traversals are specified, defaults to: SELF, MATCHING_PARAMETERS, PARAMETER_TYPE

      Example:

      // Check if parameter has @MyAnnotation anywhere in hierarchy boolean hasIt = has(MyAnnotation.class, pi); // Check only on the parameter itself boolean hasIt2 = has(MyAnnotation.class, pi, SELF);

      Type Parameters:
      A - The annotation type.
      Parameters:
      type - The annotation type to search for.
      p - The parameter to search.
      traversals - The traversal options. If not specified, defaults to SELF, MATCHING_PARAMETERS, PARAMETER_TYPE.
      Valid values: SELF, MATCHING_PARAMETERS, PARAMETER_TYPE
      Returns:
      true if the annotation is found, false otherwise.