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 77c304ad520..f7b31f7b5f4 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 @@ -19,6 +19,7 @@ package org.springframework.core.type.classreading; import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -27,6 +28,9 @@ import org.springframework.asm.MethodVisitor; import org.springframework.asm.Type; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.MethodMetadata; +import org.springframework.util.CollectionUtils; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; /** * ASM class visitor which looks for the class name and implemented types as @@ -35,6 +39,7 @@ import org.springframework.core.type.MethodMetadata; * * @author Juergen Hoeller * @author Mark Fisher + * @author Costin Leau * @since 2.5 */ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor implements AnnotationMetadata { @@ -43,12 +48,11 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor private final Set annotationSet = new LinkedHashSet(); - private final Map> metaAnnotationMap = new LinkedHashMap>(); + private final Map> metaAnnotationMap = new LinkedHashMap>(4); - private final Map> attributeMap = new LinkedHashMap>(); - - private final Set methodMetadataSet = new LinkedHashSet(); + private final Map> attributeMap = new LinkedHashMap>(4); + private final MultiValueMap methodMetadataMap = new LinkedMultiValueMap(); public AnnotationMetadataReadingVisitor(ClassLoader classLoader) { this.classLoader = classLoader; @@ -57,9 +61,7 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - MethodMetadataReadingVisitor mm = new MethodMetadataReadingVisitor(name, access, this.getClassName(), this.classLoader); - this.methodMetadataSet.add(mm); - return mm; + return new MethodMetadataReadingVisitor(name, access, this.getClassName(), this.classLoader, methodMetadataMap); } @Override @@ -132,22 +134,16 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor } public boolean hasAnnotatedMethods(String annotationType) { - for (MethodMetadata method : this.methodMetadataSet) { - if (method.isAnnotated(annotationType)) { - return true; - } - } - return false; + return methodMetadataMap.containsKey(annotationType); } public Set getAnnotatedMethods(String annotationType) { - Set annotatedMethods = new LinkedHashSet(); - for (MethodMetadata method : this.methodMetadataSet) { - if (method.isAnnotated(annotationType)) { - annotatedMethods.add(method); - } + List list = methodMetadataMap.get(annotationType); + if (CollectionUtils.isEmpty(list)) { + return new LinkedHashSet(0); } + Set annotatedMethods = new LinkedHashSet(list.size()); + annotatedMethods.addAll(list); return annotatedMethods; } - -} +} \ No newline at end of file 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 4852ab7e7cd..1bb40cbbee8 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 @@ -25,6 +25,7 @@ import org.springframework.asm.Opcodes; import org.springframework.asm.Type; import org.springframework.asm.commons.EmptyVisitor; import org.springframework.core.type.MethodMetadata; +import org.springframework.util.MultiValueMap; /** * ASM method visitor which looks for the annotations defined on the method, @@ -33,6 +34,7 @@ import org.springframework.core.type.MethodMetadata; * * @author Juergen Hoeller * @author Mark Pollack + * @author Costin Leau * @since 3.0 */ final class MethodMetadataReadingVisitor extends MethodAdapter implements MethodMetadata { @@ -45,25 +47,27 @@ final class MethodMetadataReadingVisitor extends MethodAdapter implements Method private final ClassLoader classLoader; - private final Map> attributeMap = new LinkedHashMap>(); + private final MultiValueMap methodMetadataMap; + private final Map> attributeMap = new LinkedHashMap>(2); - public MethodMetadataReadingVisitor(String name, int access, String declaringClassName, ClassLoader classLoader) { + public MethodMetadataReadingVisitor(String name, int access, String declaringClassName, ClassLoader classLoader, + MultiValueMap methodMetadataMap) { super(new EmptyVisitor()); this.name = name; this.access = access; this.declaringClassName = declaringClassName; this.classLoader = classLoader; + this.methodMetadataMap = methodMetadataMap; } - @Override public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { String className = Type.getType(desc).getClassName(); + methodMetadataMap.add(className, this); return new AnnotationAttributesReadingVisitor(className, this.attributeMap, null, this.classLoader); } - public String getMethodName() { return this.name; } @@ -91,5 +95,4 @@ final class MethodMetadataReadingVisitor extends MethodAdapter implements Method public String getDeclaringClassName() { return this.declaringClassName; } - -} +} \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReader.java b/org.springframework.core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReader.java index d146d32e6b5..428258cce9d 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReader.java +++ b/org.springframework.core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReader.java @@ -32,55 +32,42 @@ import org.springframework.core.type.ClassMetadata; * without effect on users of the core.type package. * * @author Juergen Hoeller + * @author Costin Leau * @since 2.5 */ final class SimpleMetadataReader implements MetadataReader { private final Resource resource; - - private final ClassReader classReader; - - private final ClassLoader classLoader; - - private ClassMetadata classMetadata; - - private AnnotationMetadata annotationMetadata; - + private final ClassMetadata classMetadata; + private final AnnotationMetadata annotationMetadata; SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException { - this.resource = resource; - InputStream is = this.resource.getInputStream(); + InputStream is = resource.getInputStream(); + ClassReader classReader = null; try { - this.classReader = new ClassReader(is); - } - finally { + classReader = new ClassReader(is); + } finally { is.close(); } - this.classLoader = classLoader; - } + AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader); + classReader.accept(visitor, true); + + this.annotationMetadata = visitor; + // (since AnnotationMetadataReader extends ClassMetadataReadingVisitor) + this.classMetadata = visitor; + this.resource = resource; + } public Resource getResource() { return this.resource; } public ClassMetadata getClassMetadata() { - if (this.classMetadata == null) { - ClassMetadataReadingVisitor visitor = new ClassMetadataReadingVisitor(); - this.classReader.accept(visitor, true); - this.classMetadata = visitor; - } return this.classMetadata; } public AnnotationMetadata getAnnotationMetadata() { - if (this.annotationMetadata == null) { - AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(this.classLoader); - this.classReader.accept(visitor, true); - this.annotationMetadata = visitor; - this.classMetadata = visitor; - } return this.annotationMetadata; } - -} +} \ No newline at end of file diff --git a/org.springframework.core/src/test/java/org/springframework/core/type/CachingMetadataReaderLeakTest.java b/org.springframework.core/src/test/java/org/springframework/core/type/CachingMetadataReaderLeakTest.java index 3903214bd6e..c01e3df94c5 100644 --- a/org.springframework.core/src/test/java/org/springframework/core/type/CachingMetadataReaderLeakTest.java +++ b/org.springframework.core/src/test/java/org/springframework/core/type/CachingMetadataReaderLeakTest.java @@ -48,7 +48,8 @@ public class CachingMetadataReaderLeakTest { @Test public void testSignificantLoad() throws Exception { - URL url = getClass().getResource("/org/springframework/beans/TestBean.class"); + // the biggest public class in the JDK (>60k) + URL url = getClass().getResource("/java/awt/Component.class"); assertThat(url, notNullValue()); // look at a LOT of items @@ -71,5 +72,8 @@ public class CachingMetadataReaderLeakTest { MetadataReader reader = mrf.getMetadataReader(resource); assertThat(reader, notNullValue()); } + + // useful for profiling to take snapshots + //System.in.read(); } }