Do not inspect meta-annotations on Java annotations
This commit introduces a new isInJavaLangAnnotationPackage(Annotation) method in AnnotationUtils. This method is now used in AnnotationUtils, AnnotatedElementUtils, and MetaAnnotationUtils to ensure that search algorithms do no search for meta-annotations on annotations in the "java.lang.annotation" package. The following are some empirical results from this change: - The number of times that the findAnnotation(Class,Class,Set) method in AnnotationUtils is recursively invoked while executing AnnotationUtilsTests drops from 51 to 29. - The number of times that the process(AnnotatedElement) method in AnnotationUtils.AnnotationCollector is recursively invoked while executing AnnotationUtilsTests.getRepeatableFromMethod() drops from 16 to 2. - The number of times that the doProcess() method in AnnotatedElementUtils is recursively invoked while executing the "getAnnotationAttributes() On MetaCycleAnnotatedClass with missing target meta-annotation" test in AnnotatedElementUtilsTests drops from 23 to 5. - The number of times that the findAnnotationDescriptor(Class,Set,Class) method in MetaAnnotationUtils is recursively invoked while executing the "findAnnotationDescriptor() on MetaCycleAnnotatedClass with missing target meta-annotation" test in MetaAnnotationUtilsTests drops from 16 to 8. Issue: SPR-11483
This commit is contained in:
@@ -16,9 +16,12 @@
|
||||
|
||||
package org.springframework.core.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -32,6 +35,13 @@ import static org.junit.Assert.*;
|
||||
*/
|
||||
public class AnnotatedElementUtilsTests {
|
||||
|
||||
@Test
|
||||
public void getAnnotationAttributesOnMetaCycleAnnotatedClassWithMissingTargetMetaAnnotation() {
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.getAnnotationAttributes(MetaCycleAnnotatedClass.class,
|
||||
Transactional.class.getName());
|
||||
assertNull("Should not find annotation attributes for @Transactional on MetaCycleAnnotatedClass", attributes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnotationAttributesFavorsInheritedAnnotationsOverMoreLocallyDeclaredComposedAnnotations() {
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.getAnnotationAttributes(
|
||||
@@ -61,7 +71,34 @@ public class AnnotatedElementUtilsTests {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@MetaCycle3
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.ANNOTATION_TYPE)
|
||||
@Documented
|
||||
@interface MetaCycle1 {
|
||||
}
|
||||
|
||||
@MetaCycle1
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.ANNOTATION_TYPE)
|
||||
@Documented
|
||||
@interface MetaCycle2 {
|
||||
}
|
||||
|
||||
@MetaCycle2
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
@interface MetaCycle3 {
|
||||
}
|
||||
|
||||
@MetaCycle3
|
||||
static class MetaCycleAnnotatedClass {
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
@Inherited
|
||||
@interface Transactional {
|
||||
|
||||
@@ -70,12 +107,16 @@ public class AnnotatedElementUtilsTests {
|
||||
|
||||
@Transactional
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
@Inherited
|
||||
@interface Composed1 {
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
@interface Composed2 {
|
||||
}
|
||||
|
||||
|
||||
@@ -362,6 +362,13 @@ public class AnnotationUtilsTests {
|
||||
assertNotNull(order);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findRepeatableAnnotationOnComposedAnnotation() {
|
||||
Repeatable repeatable = findAnnotation(MyRepeatableMeta.class, Repeatable.class);
|
||||
assertNotNull(repeatable);
|
||||
assertEquals(MyRepeatableContainer.class, repeatable.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRepeatableFromMethod() throws Exception {
|
||||
Method method = InterfaceWithRepeated.class.getMethod("foo");
|
||||
|
||||
Reference in New Issue
Block a user