diff --git a/org.springframework.core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java b/org.springframework.core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java index 75e91dd750..689bd0da26 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java +++ b/org.springframework.core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package org.springframework.core.type.classreading; import java.lang.annotation.Annotation; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Collection; import java.util.HashSet; @@ -29,6 +30,7 @@ import org.objectweb.asm.Type; import org.objectweb.asm.commons.EmptyVisitor; import org.springframework.core.type.AnnotationMetadata; +import org.springframework.util.ReflectionUtils; /** * ASM class visitor which looks for the class name and implemented types as @@ -62,7 +64,31 @@ class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor imple @Override public void visit(String name, Object value) { // Explicitly defined annotation attribute value. - attributes.put(name, value); + Object valueToUse = value; + if (value instanceof Type) { + try { + valueToUse = classLoader.loadClass(((Type) value).getClassName()); + } + catch (ClassNotFoundException ex) { + // Class not found - can't resolve class reference in annotation attribute. + } + } + attributes.put(name, valueToUse); + } + @Override + public void visitEnum(String name, String desc, String value) { + Object valueToUse = value; + try { + Class enumType = classLoader.loadClass(Type.getType(desc).getClassName()); + Field enumConstant = ReflectionUtils.findField(enumType, value); + if (enumConstant != null) { + valueToUse = enumConstant.get(null); + } + } + catch (Exception ex) { + // Class not found - can't resolve class reference in annotation attribute. + } + attributes.put(name, valueToUse); } @Override public void visitEnd() { @@ -70,8 +96,7 @@ class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor imple Class annotationClass = classLoader.loadClass(className); // Check declared default values of attributes in the annotation type. Method[] annotationAttributes = annotationClass.getMethods(); - for (int i = 0; i < annotationAttributes.length; i++) { - Method annotationAttribute = annotationAttributes[i]; + for (Method annotationAttribute : annotationAttributes) { String attributeName = annotationAttribute.getName(); Object defaultValue = annotationAttribute.getDefaultValue(); if (defaultValue != null && !attributes.containsKey(attributeName)) { diff --git a/org.springframework.core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java b/org.springframework.core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java index b96aeea854..0f983bdb8d 100644 --- a/org.springframework.core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java +++ b/org.springframework.core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,13 +18,17 @@ package org.springframework.core.type; import java.io.IOException; import java.io.Serializable; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import java.util.Map; import junit.framework.TestCase; import org.springframework.context.annotation.Scope; -import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.classreading.SimpleMetadataReaderFactory; import org.springframework.stereotype.Component; @@ -56,21 +60,38 @@ public class AnnotationMetadataTests extends TestCase { assertTrue(metadata.hasAnnotation(Component.class.getName())); assertTrue(metadata.hasAnnotation(Scope.class.getName())); - assertEquals(2, metadata.getAnnotationTypes().size()); + assertTrue(metadata.hasAnnotation(SpecialAttr.class.getName())); + assertEquals(3, metadata.getAnnotationTypes().size()); assertTrue(metadata.getAnnotationTypes().contains(Component.class.getName())); assertTrue(metadata.getAnnotationTypes().contains(Scope.class.getName())); + assertTrue(metadata.getAnnotationTypes().contains(SpecialAttr.class.getName())); + + Map compAttrs = metadata.getAnnotationAttributes(Component.class.getName()); + assertEquals(1, compAttrs.size()); + assertEquals("myName", compAttrs.get("value")); + Map scopeAttrs = metadata.getAnnotationAttributes(Scope.class.getName()); + assertEquals(1, scopeAttrs.size()); + assertEquals("myScope", scopeAttrs.get("value")); + Map specialAttrs = metadata.getAnnotationAttributes(SpecialAttr.class.getName()); + assertEquals(2, specialAttrs.size()); + assertEquals(String.class, specialAttrs.get("clazz")); + assertEquals(Thread.State.NEW, specialAttrs.get("state")); + } + + + @Target(ElementType.TYPE) + @Retention(RetentionPolicy.RUNTIME) + public @interface SpecialAttr { + + Class clazz(); - Map cattrs = metadata.getAnnotationAttributes(Component.class.getName()); - assertEquals(1, cattrs.size()); - assertEquals("myName", cattrs.get("value")); - Map sattrs = metadata.getAnnotationAttributes(Scope.class.getName()); - assertEquals(1, sattrs.size()); - assertEquals("myScope", sattrs.get("value")); + Thread.State state(); } @Component("myName") @Scope("myScope") + @SpecialAttr(clazz = String.class, state = Thread.State.NEW) private static class AnnotatedComponent implements Serializable { }