@@ -451,6 +451,38 @@ public static <A extends Annotation> A getMergedAnnotation(AnnotatedElement elem
451451 return AnnotationUtils .synthesizeAnnotation (attributes , annotationType , element );
452452 }
453453
454+ /**
455+ * Get <strong>all</strong> annotations of the specified {@code annotationType}
456+ * within the annotation hierarchy <em>above</em> the supplied {@code element};
457+ * and for each annotation found, merge that annotation's attributes with
458+ * <em>matching</em> attributes from annotations in lower levels of the annotation
459+ * hierarchy and synthesize the results back into an annotation of the specified
460+ * {@code annotationType}.
461+ * <p>{@link AliasFor @AliasFor} semantics are fully supported, both within a
462+ * single annotation and within annotation hierarchies.
463+ * <p>This method follows <em>get semantics</em> as described in the
464+ * {@linkplain AnnotatedElementUtils class-level javadoc}.
465+ * @param element the annotated element; never {@code null}
466+ * @param annotationType the annotation type to find; never {@code null}
467+ * @return the set of all merged, synthesized {@code Annotations} found, or an empty
468+ * set if none were found
469+ * @since 4.3
470+ * @see #getMergedAnnotation(AnnotatedElement, Class)
471+ * @see #getAllAnnotationAttributes(AnnotatedElement, String)
472+ * @see #findAllMergedAnnotations(AnnotatedElement, Class)
473+ */
474+ public static <A extends Annotation > Set <A > getAllMergedAnnotations (AnnotatedElement element ,
475+ Class <A > annotationType ) {
476+
477+ Assert .notNull (element , "AnnotatedElement must not be null" );
478+ Assert .notNull (annotationType , "annotationType must not be null" );
479+
480+ MergedAnnotationAttributesProcessor processor =
481+ new MergedAnnotationAttributesProcessor (annotationType , null , false , false , true );
482+ searchWithGetSemantics (element , annotationType , null , processor );
483+ return postProcessAndSynthesizeAggregatedResults (element , annotationType , processor .getAggregatedResults ());
484+ }
485+
454486 /**
455487 * Get the annotation attributes of <strong>all</strong> annotations of the specified
456488 * {@code annotationName} in the annotation hierarchy above the supplied
@@ -688,7 +720,7 @@ public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement ele
688720 * within the annotation hierarchy <em>above</em> the supplied {@code element};
689721 * and for each annotation found, merge that annotation's attributes with
690722 * <em>matching</em> attributes from annotations in lower levels of the annotation
691- * hierarchy and synthesize the result back into an annotation of the specified
723+ * hierarchy and synthesize the results back into an annotation of the specified
692724 * {@code annotationType}.
693725 * <p>{@link AliasFor @AliasFor} semantics are fully supported, both within a
694726 * single annotation and within annotation hierarchies.
@@ -700,6 +732,7 @@ public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement ele
700732 * set if none were found
701733 * @since 4.3
702734 * @see #findMergedAnnotation(AnnotatedElement, Class)
735+ * @see #getAllMergedAnnotations(AnnotatedElement, Class)
703736 */
704737 public static <A extends Annotation > Set <A > findAllMergedAnnotations (AnnotatedElement element ,
705738 Class <A > annotationType ) {
@@ -710,21 +743,15 @@ public static <A extends Annotation> Set<A> findAllMergedAnnotations(AnnotatedEl
710743 MergedAnnotationAttributesProcessor processor =
711744 new MergedAnnotationAttributesProcessor (annotationType , null , false , false , true );
712745 searchWithFindSemantics (element , annotationType , annotationType .getName (), processor );
713-
714- Set <A > annotations = new LinkedHashSet <A >();
715- for (AnnotationAttributes attributes : processor .getAggregatedResults ()) {
716- AnnotationUtils .postProcessAnnotationAttributes (element , attributes , false , false );
717- annotations .add (AnnotationUtils .synthesizeAnnotation (attributes , annotationType , element ));
718- }
719- return annotations ;
746+ return postProcessAndSynthesizeAggregatedResults (element , annotationType , processor .getAggregatedResults ());
720747 }
721748
722749 /**
723750 * Find all <em>repeatable annotations</em> of the specified {@code annotationType}
724751 * within the annotation hierarchy <em>above</em> the supplied {@code element};
725752 * and for each annotation found, merge that annotation's attributes with
726753 * <em>matching</em> attributes from annotations in lower levels of the annotation
727- * hierarchy and synthesize the result back into an annotation of the specified
754+ * hierarchy and synthesize the results back into an annotation of the specified
728755 * {@code annotationType}.
729756 * <p>The container type that holds the repeatable annotations will be looked up
730757 * via {@link java.lang.annotation.Repeatable}.
@@ -754,7 +781,7 @@ public static <A extends Annotation> Set<A> findMergedRepeatableAnnotations(Anno
754781 * within the annotation hierarchy <em>above</em> the supplied {@code element};
755782 * and for each annotation found, merge that annotation's attributes with
756783 * <em>matching</em> attributes from annotations in lower levels of the annotation
757- * hierarchy and synthesize the result back into an annotation of the specified
784+ * hierarchy and synthesize the results back into an annotation of the specified
758785 * {@code annotationType}.
759786 * <p>{@link AliasFor @AliasFor} semantics are fully supported, both within a
760787 * single annotation and within annotation hierarchies.
@@ -791,13 +818,7 @@ public static <A extends Annotation> Set<A> findMergedRepeatableAnnotations(Anno
791818 MergedAnnotationAttributesProcessor processor =
792819 new MergedAnnotationAttributesProcessor (annotationType , null , false , false , true );
793820 searchWithFindSemantics (element , annotationType , annotationType .getName (), containerType , processor );
794-
795- Set <A > annotations = new LinkedHashSet <A >();
796- for (AnnotationAttributes attributes : processor .getAggregatedResults ()) {
797- AnnotationUtils .postProcessAnnotationAttributes (element , attributes , false , false );
798- annotations .add (AnnotationUtils .synthesizeAnnotation (attributes , annotationType , element ));
799- }
800- return annotations ;
821+ return postProcessAndSynthesizeAggregatedResults (element , annotationType , processor .getAggregatedResults ());
801822 }
802823
803824 /**
@@ -906,13 +927,18 @@ private static <T> T searchWithGetSemanticsInAnnotations(AnnotatedElement annota
906927
907928 // Search in annotations
908929 for (Annotation annotation : annotations ) {
930+ // Note: we only check for (metaDepth > 0) due to the nuances of getMetaAnnotationTypes().
909931 if (!AnnotationUtils .isInJavaLangAnnotationPackage (annotation ) &&
910- ((annotationType != null ? annotation .annotationType () == annotationType :
911- annotation .annotationType ().getName ().equals (annotationName )) ||
912- metaDepth > 0 )) {
932+ ((annotation .annotationType () == annotationType
933+ || annotation .annotationType ().getName ().equals (annotationName )) || metaDepth > 0 )) {
913934 T result = processor .process (annotatedElement , annotation , metaDepth );
914935 if (result != null ) {
915- return result ;
936+ if (processor .aggregates () && metaDepth == 0 ) {
937+ processor .getAggregatedResults ().add (result );
938+ }
939+ else {
940+ return result ;
941+ }
916942 }
917943 }
918944 }
@@ -924,7 +950,12 @@ private static <T> T searchWithGetSemanticsInAnnotations(AnnotatedElement annota
924950 annotationName , processor , visited , metaDepth + 1 );
925951 if (result != null ) {
926952 processor .postProcess (annotatedElement , annotation , result );
927- return result ;
953+ if (processor .aggregates () && metaDepth == 0 ) {
954+ processor .getAggregatedResults ().add (result );
955+ }
956+ else {
957+ return result ;
958+ }
928959 }
929960 }
930961 }
@@ -1234,6 +1265,20 @@ private static void validateRepeatableContainerType(Class<? extends Annotation>
12341265 }
12351266 }
12361267
1268+ /**
1269+ * @since 4.3
1270+ */
1271+ private static <A extends Annotation > Set <A > postProcessAndSynthesizeAggregatedResults (AnnotatedElement element ,
1272+ Class <A > annotationType , List <AnnotationAttributes > aggregatedResults ) {
1273+
1274+ Set <A > annotations = new LinkedHashSet <A >();
1275+ for (AnnotationAttributes attributes : aggregatedResults ) {
1276+ AnnotationUtils .postProcessAnnotationAttributes (element , attributes , false , false );
1277+ annotations .add (AnnotationUtils .synthesizeAnnotation (attributes , annotationType , element ));
1278+ }
1279+ return annotations ;
1280+ }
1281+
12371282
12381283 /**
12391284 * Callback interface that is used to process annotations during a search.
@@ -1305,7 +1350,6 @@ private interface Processor<T> {
13051350 * Determine if this processor aggregates the results returned by {@link #process}.
13061351 * <p>If this method returns {@code true}, then {@link #getAggregatedResults()}
13071352 * must return a non-null value.
1308- * <p>WARNING: aggregation is currently only supported for <em>find semantics</em>.
13091353 * @return {@code true} if this processor supports aggregated results
13101354 * @see #getAggregatedResults
13111355 * @since 4.3
@@ -1319,7 +1363,6 @@ private interface Processor<T> {
13191363 * responsible for asking this processor if it {@link #aggregates} results
13201364 * and then adding the post-processed results to the list returned by this
13211365 * method.
1322- * <p>WARNING: aggregation is currently only supported for <em>find semantics</em>.
13231366 * @return the list of results aggregated by this processor; never
13241367 * {@code null} unless {@link #aggregates} returns {@code false}
13251368 * @see #aggregates
0 commit comments