diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java index 59ac62ecc9f..b15210e8e45 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java @@ -205,14 +205,14 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo } if (candidate instanceof AnnotatedBeanDefinition) { AnnotatedBeanDefinition abd = (AnnotatedBeanDefinition) candidate; - if (abd.getMetadata().hasAnnotation(Primary.class.getName())) { + if (abd.getMetadata().isAnnotated(Primary.class.getName())) { abd.setPrimary(true); } - if (abd.getMetadata().hasAnnotation(Lazy.class.getName())) { + if (abd.getMetadata().isAnnotated(Lazy.class.getName())) { Boolean value = (Boolean) abd.getMetadata().getAnnotationAttributes(Lazy.class.getName()).get("value"); abd.setLazyInit(value); } - if (abd.getMetadata().hasAnnotation(DependsOn.class.getName())) { + if (abd.getMetadata().isAnnotated(DependsOn.class.getName())) { String[] value = (String[]) abd.getMetadata().getAnnotationAttributes(DependsOn.class.getName()).get("value"); abd.setDependsOn(value); } diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java index ccd0d601c94..aa7bb0cb418 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java @@ -116,7 +116,7 @@ final class ConfigurationClass { } // A configuration class may not be final (CGLIB limitation) - if (getMetadata().hasAnnotation(Configuration.class.getName())) { + if (getMetadata().isAnnotated(Configuration.class.getName())) { if (getMetadata().isFinal()) { problemReporter.error(new FinalConfigurationProblem()); } diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java index 6419d616121..00c9181636a 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java @@ -36,6 +36,7 @@ import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.io.Resource; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.MethodMetadata; @@ -128,11 +129,11 @@ class ConfigurationClassBeanDefinitionReader { List names = new ArrayList(Arrays.asList((String[]) beanAttributes.get("name"))); String beanName = (names.size() > 0 ? names.remove(0) : method.getMetadata().getMethodName()); for (String alias : names) { - registry.registerAlias(beanName, alias); + this.registry.registerAlias(beanName, alias); } // has this already been overriden (i.e.: via XML)? - if (registry.containsBeanDefinition(beanName)) { + if (this.registry.containsBeanDefinition(beanName)) { BeanDefinition existingBeanDef = registry.getBeanDefinition(beanName); // is the existing bean definition one that was created from a configuration class? if (!(existingBeanDef instanceof ConfigurationClassBeanDefinition)) { @@ -146,19 +147,19 @@ class ConfigurationClassBeanDefinitionReader { } } - if (metadata.hasAnnotation(Primary.class.getName())) { + if (metadata.isAnnotated(Primary.class.getName())) { beanDef.setPrimary(true); } // is this bean to be instantiated lazily? - if (metadata.hasAnnotation(Lazy.class.getName())) { + if (metadata.isAnnotated(Lazy.class.getName())) { beanDef.setLazyInit((Boolean) metadata.getAnnotationAttributes(Lazy.class.getName()).get("value")); } - else if (configClass.getMetadata().hasAnnotation(Lazy.class.getName())){ + else if (configClass.getMetadata().isAnnotated(Lazy.class.getName())){ beanDef.setLazyInit((Boolean) configClass.getMetadata().getAnnotationAttributes(Lazy.class.getName()).get("value")); } - if (metadata.hasAnnotation(DependsOn.class.getName())) { + if (metadata.isAnnotated(DependsOn.class.getName())) { String[] dependsOn = (String[]) metadata.getAnnotationAttributes(DependsOn.class.getName()).get("value"); if (dependsOn.length > 0) { beanDef.setDependsOn(dependsOn); @@ -232,7 +233,7 @@ class ConfigurationClassBeanDefinitionReader { @Override public boolean isFactoryMethod(Method candidate) { - return (super.isFactoryMethod(candidate) && candidate.isAnnotationPresent(Bean.class)); + return (super.isFactoryMethod(candidate) && AnnotationUtils.findAnnotation(candidate, Bean.class) != null); } @Override diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassMethod.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassMethod.java index fd9ea2a9a88..c1379e44963 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassMethod.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassMethod.java @@ -57,7 +57,7 @@ final class ConfigurationClassMethod { } public void validate(ProblemReporter problemReporter) { - if (this.declaringClass.getMetadata().hasAnnotation(Configuration.class.getName()) && !getMetadata().isOverridable()) { + if (this.declaringClass.getMetadata().isAnnotated(Configuration.class.getName()) && !getMetadata().isOverridable()) { problemReporter.error(new NonOverridableMethodError()); } } diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java index 9be11235f58..64ed5bd3e1c 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java @@ -121,7 +121,7 @@ class ConfigurationClassParser { } protected void doProcessConfigurationClass(ConfigurationClass configClass, AnnotationMetadata metadata) throws IOException { - if (metadata.hasAnnotation(Import.class.getName())) { + if (metadata.isAnnotated(Import.class.getName())) { processImport(configClass, (String[]) metadata.getAnnotationAttributes(Import.class.getName()).get("value")); } Set methods = metadata.getAnnotatedMethods(Bean.class.getName()); @@ -146,7 +146,7 @@ class ConfigurationClassParser { private void processClassToImport(String classToImport) throws IOException { MetadataReader reader = this.metadataReaderFactory.getMetadataReader(classToImport); AnnotationMetadata metadata = reader.getAnnotationMetadata(); - if (!metadata.hasAnnotation(Configuration.class.getName())) { + if (!metadata.isAnnotated(Configuration.class.getName())) { this.problemReporter.error( new NonAnnotatedConfigurationProblem(metadata.getClassName(), reader.getResource(), metadata)); } diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java index 4f3cf493ad4..75d029d083b 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java @@ -218,11 +218,11 @@ public class ConfigurationClassPostProcessor implements BeanFactoryPostProcessor } if (metadata != null) { - if (metadata.hasAnnotation(Configuration.class.getName())) { + if (metadata.isAnnotated(Configuration.class.getName())) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL); return true; } - else if (metadata.hasAnnotation(Component.class.getName())) { + else if (metadata.isAnnotated(Component.class.getName())) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE); return true; } diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation/configuration/ScopingTests.java b/org.springframework.context/src/test/java/org/springframework/context/annotation/configuration/ScopingTests.java index bd5e9695b80..01c9331a911 100644 --- a/org.springframework.context/src/test/java/org/springframework/context/annotation/configuration/ScopingTests.java +++ b/org.springframework.context/src/test/java/org/springframework/context/annotation/configuration/ScopingTests.java @@ -66,7 +66,9 @@ public class ScopingTests { @After public void tearDown() throws Exception { - ctx.close(); + if (ctx != null) { + ctx.close(); + } ctx = null; customScope = null; } @@ -328,7 +330,6 @@ public class ScopingTests { return tb; } - @Bean @MyProxiedScope public TestBean scopedProxyClass() { TestBean tb = new TestBean(); @@ -361,6 +362,7 @@ public class ScopingTests { @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) + @Bean @Scope(value=SCOPE, proxyMode=ScopedProxyMode.TARGET_CLASS) @interface MyProxiedScope { } diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation5/MyRepository.java b/org.springframework.context/src/test/java/org/springframework/context/annotation5/MyRepository.java new file mode 100644 index 00000000000..c7a8094f635 --- /dev/null +++ b/org.springframework.context/src/test/java/org/springframework/context/annotation5/MyRepository.java @@ -0,0 +1,37 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.context.annotation5; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Repository; + +/** + * @author Juergen Hoeller + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Repository +@Primary +@Lazy +public @interface MyRepository { +} diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation5/OtherFooDao.java b/org.springframework.context/src/test/java/org/springframework/context/annotation5/OtherFooDao.java index c9972ff9d36..5434c4f4b5c 100644 --- a/org.springframework.context/src/test/java/org/springframework/context/annotation5/OtherFooDao.java +++ b/org.springframework.context/src/test/java/org/springframework/context/annotation5/OtherFooDao.java @@ -25,8 +25,7 @@ import org.springframework.stereotype.Repository; /** * @author Juergen Hoeller */ -@Repository -@Primary @Lazy +@MyRepository public class OtherFooDao implements FooDao { public String findFoo(int id) { diff --git a/org.springframework.core/src/main/java/org/springframework/core/type/AnnotationMetadata.java b/org.springframework.core/src/main/java/org/springframework/core/type/AnnotationMetadata.java index ec7c64b89cf..3366030cd23 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/type/AnnotationMetadata.java +++ b/org.springframework.core/src/main/java/org/springframework/core/type/AnnotationMetadata.java @@ -61,9 +61,21 @@ public interface AnnotationMetadata extends ClassMetadata { */ boolean hasMetaAnnotation(String metaAnnotationType); + /** + * Determine whether the underlying class has an annotation or + * meta-annotation of the given type defined. + *

This is equivalent to a "hasAnnotation || hasMetaAnnotation" + * check. If this method returns true, then + * {@link #getAnnotationAttributes} will return a non-null Map. + * @param annotationType the annotation type to look for + * @return whether a matching annotation is defined + */ + boolean isAnnotated(String annotationType); + /** * Retrieve the attributes of the annotation of the given type, - * if any (i.e. if defined on the underlying class). + * if any (i.e. if defined on the underlying class, as direct + * annotation or as meta-annotation). * @param annotationType the annotation type to look for * @return a Map of attributes, with the attribute name as key (e.g. "value") * and the defined attribute value as Map value. This return value will be @@ -73,15 +85,9 @@ public interface AnnotationMetadata extends ClassMetadata { /** * Retrieve the method metadata for all methods that are annotated - * with at least one annotation type. - * @return a Set of {@link MethodMetadata} for methods that have annotations. - * The return value will be an empty set if no annotated methods are found. - */ - Set getAnnotatedMethods(); - - /** - * Retrieve the method metadata for all methods that have the - * given annotation type. + * (or meta-annotated) with the given annotation type. + *

For any returned method, {@link MethodMetadata#isAnnotated} will + * return true for the given annotation type. * @param annotationType the annotation type to look for * @return a Set of {@link MethodMetadata} for methods that have a matching * annotation. The return value will be an empty set if no methods match diff --git a/org.springframework.core/src/main/java/org/springframework/core/type/MethodMetadata.java b/org.springframework.core/src/main/java/org/springframework/core/type/MethodMetadata.java index 62d94efbda3..ae32ce6e457 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/type/MethodMetadata.java +++ b/org.springframework.core/src/main/java/org/springframework/core/type/MethodMetadata.java @@ -17,14 +17,13 @@ package org.springframework.core.type; import java.util.Map; -import java.util.Set; /** * Interface that defines abstract access to the annotations of a specific * class, in a form that does not require that class to be loaded yet. * - * @author Mark Pollack * @author Juergen Hoeller + * @author Mark Pollack * @since 3.0 * @see StandardMethodMetadata * @see AnnotationMetadata#getAnnotatedMethods @@ -53,22 +52,17 @@ public interface MethodMetadata { boolean isOverridable(); /** - * Return the names of all annotation types defined on the underlying method. - * @return the annotation type names, or an empty Set if none found - */ - Set getAnnotationTypes(); - - /** - * Determine whether the underlying method has an annotation of the given - * type defined. + * Determine whether the underlying method has an annotation or + * meta-annotation of the given type defined. * @param annotationType the annotation type to look for * @return whether a matching annotation is defined */ - boolean hasAnnotation(String annotationType); + boolean isAnnotated(String annotationType); /** * Retrieve the attributes of the annotation of the given type, - * if any (i.e. if defined on the underlying method). + * if any (i.e. if defined on the underlying method, as direct + * annotation or as meta-annotation). * @param annotationType the annotation type to look for * @return a Map of attributes, with the attribute name as key (e.g. "value") * and the defined attribute value as Map value. This return value will be diff --git a/org.springframework.core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java b/org.springframework.core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java index 77302c6095f..100e30516bc 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java +++ b/org.springframework.core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java @@ -98,6 +98,21 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements return false; } + public boolean isAnnotated(String annotationType) { + Annotation[] anns = getIntrospectedClass().getAnnotations(); + for (Annotation ann : anns) { + if (ann.annotationType().getName().equals(annotationType)) { + return true; + } + for (Annotation metaAnn : ann.annotationType().getAnnotations()) { + if (metaAnn.annotationType().getName().equals(annotationType)) { + return true; + } + } + } + return false; + } + public Map getAnnotationAttributes(String annotationType) { Annotation[] anns = getIntrospectedClass().getAnnotations(); for (Annotation ann : anns) { @@ -113,25 +128,22 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements return null; } - public Set getAnnotatedMethods() { - Method[] methods = getIntrospectedClass().getDeclaredMethods(); - Set annotatedMethods = new LinkedHashSet(); - for (Method method : methods) { - if (method.getAnnotations().length > 0) { - annotatedMethods.add(new StandardMethodMetadata(method)); - } - } - return annotatedMethods; - } - public Set getAnnotatedMethods(String annotationType) { Method[] methods = getIntrospectedClass().getDeclaredMethods(); Set annotatedMethods = new LinkedHashSet(); for (Method method : methods) { - Annotation[] methodAnnotations = method.getAnnotations(); - for (Annotation ann : methodAnnotations) { + for (Annotation ann : method.getAnnotations()) { if (ann.annotationType().getName().equals(annotationType)) { annotatedMethods.add(new StandardMethodMetadata(method)); + break; + } + else { + for (Annotation metaAnn : ann.annotationType().getAnnotations()) { + if (metaAnn.annotationType().getName().equals(annotationType)) { + annotatedMethods.add(new StandardMethodMetadata(method)); + break; + } + } } } } diff --git a/org.springframework.core/src/main/java/org/springframework/core/type/StandardMethodMetadata.java b/org.springframework.core/src/main/java/org/springframework/core/type/StandardMethodMetadata.java index be25bf42391..9aaf20af72a 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/type/StandardMethodMetadata.java +++ b/org.springframework.core/src/main/java/org/springframework/core/type/StandardMethodMetadata.java @@ -19,9 +19,7 @@ package org.springframework.core.type; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.HashSet; import java.util.Map; -import java.util.Set; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.Assert; @@ -30,8 +28,8 @@ import org.springframework.util.Assert; * {@link MethodMetadata} implementation that uses standard reflection * to introspect a given Method. * - * @author Mark Pollack * @author Juergen Hoeller + * @author Mark Pollack * @since 3.0 */ public class StandardMethodMetadata implements MethodMetadata { @@ -72,21 +70,17 @@ public class StandardMethodMetadata implements MethodMetadata { return (!isStatic() && !isFinal() && !Modifier.isPrivate(this.introspectedMethod.getModifiers())); } - public Set getAnnotationTypes() { - Set types = new HashSet(); - Annotation[] anns = this.introspectedMethod.getAnnotations(); - for (Annotation ann : anns) { - types.add(ann.annotationType().getName()); - } - return types; - } - - public boolean hasAnnotation(String annotationType) { + public boolean isAnnotated(String annotationType) { Annotation[] anns = this.introspectedMethod.getAnnotations(); for (Annotation ann : anns) { if (ann.annotationType().getName().equals(annotationType)) { return true; } + for (Annotation metaAnn : ann.annotationType().getAnnotations()) { + if (metaAnn.annotationType().getName().equals(annotationType)) { + return true; + } + } } return false; } diff --git a/org.springframework.core/src/main/java/org/springframework/core/type/classreading/AnnotationAttributesReadingVisitor.java b/org.springframework.core/src/main/java/org/springframework/core/type/classreading/AnnotationAttributesReadingVisitor.java index a21d022873c..fc383cb617f 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/type/classreading/AnnotationAttributesReadingVisitor.java +++ b/org.springframework.core/src/main/java/org/springframework/core/type/classreading/AnnotationAttributesReadingVisitor.java @@ -28,9 +28,9 @@ import java.util.Set; import org.springframework.asm.AnnotationVisitor; import org.springframework.asm.Type; import org.springframework.asm.commons.EmptyVisitor; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; -import org.springframework.core.annotation.AnnotationUtils; /** * ASM visitor which looks for the annotations defined on a class or method. @@ -42,13 +42,13 @@ final class AnnotationAttributesReadingVisitor implements AnnotationVisitor { private final String annotationType; - private final Map> annotationMap; + private final Map> attributesMap; private final Map> metaAnnotationMap; private final ClassLoader classLoader; - private final Map attributes = new LinkedHashMap(); + private final Map localAttributes = new LinkedHashMap(); public AnnotationAttributesReadingVisitor( @@ -56,7 +56,7 @@ final class AnnotationAttributesReadingVisitor implements AnnotationVisitor { Map> metaAnnotationMap, ClassLoader classLoader) { this.annotationType = annotationType; - this.annotationMap = attributesMap; + this.attributesMap = attributesMap; this.metaAnnotationMap = metaAnnotationMap; this.classLoader = classLoader; } @@ -67,7 +67,7 @@ final class AnnotationAttributesReadingVisitor implements AnnotationVisitor { if (valueToUse instanceof Type) { valueToUse = ((Type) value).getClassName(); } - this.attributes.put(name, valueToUse); + this.localAttributes.put(name, valueToUse); } public void visitEnum(String name, String desc, String value) { @@ -82,7 +82,7 @@ final class AnnotationAttributesReadingVisitor implements AnnotationVisitor { catch (Exception ex) { // Class not found - can't resolve class reference in annotation attribute. } - this.attributes.put(name, valueToUse); + this.localAttributes.put(name, valueToUse); } public AnnotationVisitor visitAnnotation(String name, String desc) { @@ -96,7 +96,7 @@ final class AnnotationAttributesReadingVisitor implements AnnotationVisitor { if (newValue instanceof Type) { newValue = ((Type) value).getClassName(); } - Object existingValue = attributes.get(attrName); + Object existingValue = localAttributes.get(attrName); if (existingValue != null) { newValue = ObjectUtils.addObjectToArray((Object[]) existingValue, newValue); } @@ -105,7 +105,7 @@ final class AnnotationAttributesReadingVisitor implements AnnotationVisitor { newArray[0] = newValue; newValue = newArray; } - attributes.put(attrName, newValue); + localAttributes.put(attrName, newValue); } public void visitEnum(String name, String desc, String value) { } @@ -121,7 +121,7 @@ final class AnnotationAttributesReadingVisitor implements AnnotationVisitor { } public void visitEnd() { - this.annotationMap.put(this.annotationType, this.attributes); + this.attributesMap.put(this.annotationType, this.localAttributes); try { Class annotationClass = this.classLoader.loadClass(this.annotationType); // Check declared default values of attributes in the annotation type. @@ -129,23 +129,23 @@ final class AnnotationAttributesReadingVisitor implements AnnotationVisitor { for (Method annotationAttribute : annotationAttributes) { String attributeName = annotationAttribute.getName(); Object defaultValue = annotationAttribute.getDefaultValue(); - if (defaultValue != null && !this.attributes.containsKey(attributeName)) { - this.attributes.put(attributeName, defaultValue); + if (defaultValue != null && !this.localAttributes.containsKey(attributeName)) { + this.localAttributes.put(attributeName, defaultValue); } } // Register annotations that the annotation type is annotated with. - if (this.metaAnnotationMap != null) { - Set metaAnnotationTypeNames = new LinkedHashSet(); - for (Annotation metaAnnotation : annotationClass.getAnnotations()) { - metaAnnotationTypeNames.add(metaAnnotation.annotationType().getName()); - if (!this.annotationMap.containsKey(metaAnnotation.annotationType().getName())) { - this.annotationMap.put(metaAnnotation.annotationType().getName(), - AnnotationUtils.getAnnotationAttributes(metaAnnotation, true)); - } - for (Annotation metaMetaAnnotation : metaAnnotation.annotationType().getAnnotations()) { - metaAnnotationTypeNames.add(metaMetaAnnotation.annotationType().getName()); - } + Set metaAnnotationTypeNames = new LinkedHashSet(); + for (Annotation metaAnnotation : annotationClass.getAnnotations()) { + metaAnnotationTypeNames.add(metaAnnotation.annotationType().getName()); + if (!this.attributesMap.containsKey(metaAnnotation.annotationType().getName())) { + this.attributesMap.put(metaAnnotation.annotationType().getName(), + AnnotationUtils.getAnnotationAttributes(metaAnnotation, true)); } + for (Annotation metaMetaAnnotation : metaAnnotation.annotationType().getAnnotations()) { + metaAnnotationTypeNames.add(metaMetaAnnotation.annotationType().getName()); + } + } + if (this.metaAnnotationMap != null) { this.metaAnnotationMap.put(this.annotationType, metaAnnotationTypeNames); } } 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 cd5109bb19e..26eeffc4914 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 @@ -39,6 +39,8 @@ import org.springframework.core.type.MethodMetadata; */ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor implements AnnotationMetadata { + private final ClassLoader classLoader; + private final Set annotationSet = new LinkedHashSet(); private final Map> metaAnnotationMap = new LinkedHashMap>(); @@ -47,8 +49,6 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor private final Set methodMetadataSet = new LinkedHashSet(); - private final ClassLoader classLoader; - public AnnotationMetadataReadingVisitor(ClassLoader classLoader) { this.classLoader = classLoader; @@ -92,24 +92,18 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor return false; } - public Map getAnnotationAttributes(String annotationType) { - return this.attributeMap.get(annotationType); + public boolean isAnnotated(String annotationType) { + return this.attributeMap.containsKey(annotationType); } - public Set getAnnotatedMethods() { - Set annotatedMethods = new LinkedHashSet(); - for (MethodMetadata method : this.methodMetadataSet) { - if (!method.getAnnotationTypes().isEmpty()) { - annotatedMethods.add(method); - } - } - return annotatedMethods; + public Map getAnnotationAttributes(String annotationType) { + return this.attributeMap.get(annotationType); } public Set getAnnotatedMethods(String annotationType) { Set annotatedMethods = new LinkedHashSet(); for (MethodMetadata method : this.methodMetadataSet) { - if (method.hasAnnotation(annotationType)) { + if (method.isAnnotated(annotationType)) { annotatedMethods.add(method); } } diff --git a/org.springframework.core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java b/org.springframework.core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java index 4a9718f7fc8..e311508b78a 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java +++ b/org.springframework.core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java @@ -18,7 +18,6 @@ package org.springframework.core.type.classreading; import java.util.LinkedHashMap; import java.util.Map; -import java.util.Set; import org.springframework.asm.AnnotationVisitor; import org.springframework.asm.MethodAdapter; @@ -32,8 +31,8 @@ import org.springframework.core.type.MethodMetadata; * exposing them through the {@link org.springframework.core.type.MethodMetadata} * interface. * - * @author Mark Pollack * @author Juergen Hoeller + * @author Mark Pollack * @since 3.0 */ final class MethodMetadataReadingVisitor extends MethodAdapter implements MethodMetadata { @@ -44,7 +43,7 @@ final class MethodMetadataReadingVisitor extends MethodAdapter implements Method private final ClassLoader classLoader; - private final Map> annotationMap = new LinkedHashMap>(); + private final Map> attributeMap = new LinkedHashMap>(); public MethodMetadataReadingVisitor(String name, int access, ClassLoader classLoader) { @@ -55,6 +54,13 @@ final class MethodMetadataReadingVisitor extends MethodAdapter implements Method } + @Override + public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { + String className = Type.getType(desc).getClassName(); + return new AnnotationAttributesReadingVisitor(className, this.attributeMap, null, this.classLoader); + } + + public String getMethodName() { return this.name; } @@ -71,23 +77,12 @@ final class MethodMetadataReadingVisitor extends MethodAdapter implements Method return (!isStatic() && !isFinal() && ((this.access & Opcodes.ACC_PRIVATE) == 0)); } - public Set getAnnotationTypes() { - return this.annotationMap.keySet(); + public boolean isAnnotated(String annotationType) { + return this.attributeMap.containsKey(annotationType); } - public boolean hasAnnotation(String annotationType) { - return this.annotationMap.containsKey(annotationType); - } - public Map getAnnotationAttributes(String annotationType) { - return this.annotationMap.get(annotationType); - } - - - @Override - public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { - String className = Type.getType(desc).getClassName(); - return new AnnotationAttributesReadingVisitor(className, this.annotationMap, null, this.classLoader); + return this.attributeMap.get(annotationType); } } 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 f2303e8593b..b41fecba7a8 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 @@ -84,11 +84,10 @@ public class AnnotationMetadataTests extends TestCase { } private void doTestMethodAnnotationInfo(AnnotationMetadata classMetadata) { - Set methods = classMetadata.getAnnotatedMethods("org.springframework.beans.factory.annotation.Autowired"); + Set methods = classMetadata.getAnnotatedMethods(Autowired.class.getName()); assertEquals(1, methods.size()); for (MethodMetadata methodMetadata : methods) { - Set annotationTypes = methodMetadata.getAnnotationTypes(); - assertEquals(1, annotationTypes.size()); + assertTrue(methodMetadata.isAnnotated(Autowired.class.getName())); } }