Extend AnnotationMetadata and MethodMetadata

Update AnnotationMetadata and MethodMetadata to extend from a new
AnnotatedTypeMetadata base interface containing the methods that are
common to both. Also introduce new getAllAnnotationAttributes methods
providing MultiValueMap access to both annotation and meta-annotation
attributes.

Existing classreading and standard implementations have been
refactored to support the new interface.
This commit is contained in:
Phillip Webb
2013-02-20 09:38:43 -08:00
parent eb1776e79d
commit 8e445f3a21
11 changed files with 537 additions and 247 deletions
@@ -18,7 +18,9 @@ package org.springframework.core.type;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@@ -29,10 +31,12 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.Test;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
@@ -45,6 +49,7 @@ import org.springframework.stereotype.Component;
*
* @author Juergen Hoeller
* @author Chris Beams
* @author Phillip Webb
*/
public class AnnotationMetadataTests {
@@ -93,7 +98,7 @@ public class AnnotationMetadataTests {
assertThat(metadata.hasAnnotation(Component.class.getName()), is(true));
assertThat(metadata.hasAnnotation(Scope.class.getName()), is(true));
assertThat(metadata.hasAnnotation(SpecialAttr.class.getName()), is(true));
assertThat(metadata.getAnnotationTypes().size(), is(3));
assertThat(metadata.getAnnotationTypes().size(), is(5));
assertThat(metadata.getAnnotationTypes().contains(Component.class.getName()), is(true));
assertThat(metadata.getAnnotationTypes().contains(Scope.class.getName()), is(true));
assertThat(metadata.getAnnotationTypes().contains(SpecialAttr.class.getName()), is(true));
@@ -104,6 +109,15 @@ public class AnnotationMetadataTests {
AnnotationAttributes scopeAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(Scope.class.getName());
assertThat(scopeAttrs.size(), is(1));
assertThat(scopeAttrs.getString("value"), is("myScope"));
Set<MethodMetadata> methods = metadata.getAnnotatedMethods(DirectAnnotation.class.getName());
MethodMetadata method = methods.iterator().next();
assertEquals("direct", method.getAnnotationAttributes(DirectAnnotation.class.getName()).get("value"));
List<Object> allMeta = method.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("value");
assertThat(new HashSet<Object>(allMeta), is(equalTo(new HashSet<Object>(Arrays.asList("direct", "meta")))));
assertTrue(metadata.isAnnotated(IsAnnotatedAnnotation.class.getName()));
{ // perform tests with classValuesAsString = false (the default)
AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(SpecialAttr.class.getName());
assertThat(specialAttrs.size(), is(6));
@@ -137,6 +151,10 @@ public class AnnotationMetadataTests {
assertTrue(optionalArray[0].getEnum("anEnum").equals(SomeEnum.DEFAULT));
assertArrayEquals(new Class[]{Void.class}, (Class[])optionalArray[0].get("classArray"));
assertArrayEquals(new Class[]{Void.class}, optionalArray[0].getClassArray("classArray"));
assertEquals("direct", metadata.getAnnotationAttributes(DirectAnnotation.class.getName()).get("value"));
allMeta = metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("value");
assertThat(new HashSet<Object>(allMeta), is(equalTo(new HashSet<Object>(Arrays.asList("direct", "meta")))));
}
{ // perform tests with classValuesAsString = true
AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(SpecialAttr.class.getName(), true);
@@ -161,6 +179,10 @@ public class AnnotationMetadataTests {
AnnotationAttributes[] optionalArray = specialAttrs.getAnnotationArray("optionalArray");
assertArrayEquals(new String[]{Void.class.getName()}, (String[])optionalArray[0].get("classArray"));
assertArrayEquals(new String[]{Void.class.getName()}, optionalArray[0].getStringArray("classArray"));
assertEquals(metadata.getAnnotationAttributes(DirectAnnotation.class.getName()).get("value"), "direct");
allMeta = metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("value");
assertThat(new HashSet<Object>(allMeta), is(equalTo(new HashSet<Object>(Arrays.asList("direct", "meta")))));
}
}
@@ -201,6 +223,29 @@ public class AnnotationMetadataTests {
NestedAnno[] optionalArray() default {@NestedAnno(value="optional", anEnum=SomeEnum.DEFAULT, classArray=Void.class)};
}
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface DirectAnnotation {
String value();
}
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface IsAnnotatedAnnotation {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@DirectAnnotation("meta")
@IsAnnotatedAnnotation
public @interface MetaAnnotation {
}
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@MetaAnnotation
public @interface MetaMetaAnnotation {
}
@Component("myName")
@Scope("myScope")
@@ -211,6 +256,8 @@ public class AnnotationMetadataTests {
@NestedAnno(value = "na1", anEnum = SomeEnum.LABEL2, classArray = {Number.class})
})
@SuppressWarnings({"serial", "unused"})
@DirectAnnotation("direct")
@MetaMetaAnnotation
private static class AnnotatedComponent implements Serializable {
@TestAutowired
@@ -219,6 +266,11 @@ public class AnnotationMetadataTests {
public void doSleep() {
}
@DirectAnnotation("direct")
@MetaMetaAnnotation
public void meta() {
}
}
}