@@ -67,6 +67,18 @@ private ClassUtils() {
6767 private static final Map <Class <?>, Map <Class <?>, List <Field >>> fields =
6868 new HashMap <Class <?>, Map <Class <?>, List <Field >>>();
6969
70+ /**
71+ * This maps a base class (key1) to a map of annotation classes (key2), which
72+ * then maps to a list of {@link Method} instances, being the set of methods
73+ * in the base class with the specified annotation.
74+ * <p>
75+ * This map serves as a cache, as these annotations should not change at
76+ * runtime and thus can alleviate the frequency of method querying.
77+ * </p>
78+ */
79+ private static final Map <Class <?>, Map <Class <?>, List <Method >>> methods =
80+ new HashMap <Class <?>, Map <Class <?>, List <Method >>>();
81+
7082 // -- Class loading, querying and reflection --
7183
7284 /**
@@ -300,8 +312,13 @@ public static URL getLocation(final Class<?> c) {
300312 public static <A extends Annotation > List <Method > getAnnotatedMethods (
301313 final Class <?> c , final Class <A > annotationClass )
302314 {
303- final ArrayList <Method > methods = new ArrayList <Method >();
304- getAnnotatedMethods (c , annotationClass , methods );
315+ List <Method > methods = lookupMethods (c , annotationClass );
316+
317+ if (methods == null ) {
318+ methods = new ArrayList <Method >();
319+ getAnnotatedMethods (c , annotationClass , methods );
320+ }
321+
305322 return methods ;
306323 }
307324
@@ -344,6 +361,8 @@ public static <A extends Annotation> List<Method> getAnnotatedMethods(
344361 final A ann = m .getAnnotation (annotationClass );
345362 if (ann != null ) methods .add (m );
346363 }
364+
365+ mapMethods (c , annotationClass , methods );
347366 }
348367
349368 /**
@@ -560,6 +579,26 @@ private static <A extends Annotation> void mapFields(Class<?> c,
560579 map .put (annotationClass , annotatedFields );
561580 }
562581
582+ /**
583+ * Populates the provided list with {@link Method} entries of the given base
584+ * class which are annotated with the specified annotation type.
585+ *
586+ * @param c Base class
587+ * @param annotationClass Annotation type
588+ * @param annotatedFields Method list to populate
589+ */
590+ private static <A extends Annotation > void mapMethods (final Class <?> c ,
591+ final Class <A > annotationClass , List <Method > annotatedMethods )
592+ {
593+ Map <Class <?>, List <Method >> map = methods .get (c );
594+ if (map == null ) {
595+ map = new HashMap <Class <?>, List <Method >>();
596+ methods .put (c , map );
597+ }
598+
599+ map .put (annotationClass , annotatedMethods );
600+ }
601+
563602 /**
564603 * @param c Base class
565604 * @param annotationClass Annotation type
@@ -577,6 +616,22 @@ private static <A extends Annotation> List<Field> lookupFields(
577616 return annotatedFields ;
578617 }
579618
619+ /**
620+ * @param c Base class
621+ * @param annotationClass Annotation type
622+ * @return Cached list of Methods in the base class with the specified
623+ * annotation, or null if a cached list does not exist.
624+ */
625+ private static <A extends Annotation > List <Method > lookupMethods (
626+ final Class <?> c , final Class <A > annotationClass )
627+ {
628+ List <Method > annotatedFields = null ;
629+ Map <Class <?>, List <Method >> annotationTypes = methods .get (c );
630+ if (annotationTypes != null ) {
631+ annotatedFields = annotationTypes .get (annotationClass );
632+ }
633+ return annotatedFields ;
634+ }
580635 // -- Deprecated methods --
581636
582637 /** @deprecated use {@link ConversionUtils#convert(Object, Class)} */
0 commit comments