From 428b0decd5c2fab598aae82c4060a76a557a0379 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 3 Apr 2018 10:30:34 +0200 Subject: [PATCH] DATACMNS-1284 - Polishing. Backport of 5eb10a0 but leaving out the Stream execution optimizations. Related ticket: DATACMNS-1206. Original commit: 5eb10a0. --- .../DefaultProjectionInformation.java | 2 +- .../data/type/MethodsMetadata.java | 1 + .../DefaultMethodsMetadataReader.java | 114 +++++++++++++----- .../MethodsMetadataReader.java | 5 +- .../MethodsMetadataReaderFactory.java | 1 - .../MethodsMetadataReadingVisitor.java | 107 ---------------- ...MethodsMetadataReaderFactoryUnitTests.java | 1 + ...DefaultMethodsMetadataReaderUnitTests.java | 1 - 8 files changed, 90 insertions(+), 142 deletions(-) rename src/main/java/org/springframework/data/type/{ => classreading}/MethodsMetadataReader.java (85%) delete mode 100644 src/main/java/org/springframework/data/type/classreading/MethodsMetadataReadingVisitor.java diff --git a/src/main/java/org/springframework/data/projection/DefaultProjectionInformation.java b/src/main/java/org/springframework/data/projection/DefaultProjectionInformation.java index 3492aa421..73cdb1106 100644 --- a/src/main/java/org/springframework/data/projection/DefaultProjectionInformation.java +++ b/src/main/java/org/springframework/data/projection/DefaultProjectionInformation.java @@ -30,7 +30,7 @@ import java.util.Set; import org.springframework.beans.BeanUtils; import org.springframework.core.type.MethodMetadata; import org.springframework.data.type.MethodsMetadata; -import org.springframework.data.type.MethodsMetadataReader; +import org.springframework.data.type.classreading.MethodsMetadataReader; import org.springframework.data.type.classreading.MethodsMetadataReaderFactory; import org.springframework.data.util.ReflectionUtils; import org.springframework.util.Assert; diff --git a/src/main/java/org/springframework/data/type/MethodsMetadata.java b/src/main/java/org/springframework/data/type/MethodsMetadata.java index 49f73e993..261d55bb3 100644 --- a/src/main/java/org/springframework/data/type/MethodsMetadata.java +++ b/src/main/java/org/springframework/data/type/MethodsMetadata.java @@ -19,6 +19,7 @@ import java.util.Set; import org.springframework.core.type.ClassMetadata; import org.springframework.core.type.MethodMetadata; +import org.springframework.data.type.classreading.MethodsMetadataReader; /** * Interface that defines abstract metadata of a specific class, in a form that does not require that class to be loaded diff --git a/src/main/java/org/springframework/data/type/classreading/DefaultMethodsMetadataReader.java b/src/main/java/org/springframework/data/type/classreading/DefaultMethodsMetadataReader.java index 509a6c8c5..809edf5dd 100644 --- a/src/main/java/org/springframework/data/type/classreading/DefaultMethodsMetadataReader.java +++ b/src/main/java/org/springframework/data/type/classreading/DefaultMethodsMetadataReader.java @@ -15,17 +15,28 @@ */ package org.springframework.data.type.classreading; +import lombok.Getter; + import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; import org.springframework.asm.ClassReader; +import org.springframework.asm.MethodVisitor; +import org.springframework.asm.Opcodes; +import org.springframework.asm.Type; import org.springframework.core.NestedIOException; import org.springframework.core.io.Resource; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.ClassMetadata; +import org.springframework.core.type.MethodMetadata; +import org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor; +import org.springframework.core.type.classreading.MethodMetadataReadingVisitor; import org.springframework.data.type.MethodsMetadata; -import org.springframework.data.type.MethodsMetadataReader; +import org.springframework.util.Assert; /** * {@link MethodsMetadataReader} implementation based on an ASM {@link org.springframework.asm.ClassReader}. @@ -35,6 +46,7 @@ import org.springframework.data.type.MethodsMetadataReader; * @since 2.1 * @since 1.11.11 */ +@Getter class DefaultMethodsMetadataReader implements MethodsMetadataReader { private final Resource resource; @@ -74,38 +86,80 @@ class DefaultMethodsMetadataReader implements MethodsMetadataReader { methodsMetadata = visitor; } - /* - * (non-Javadoc) - * @see org.springframework.core.type.classreading.MetadataReader#getResource() + /** + * ASM class visitor which looks for the class name and implemented types as well as for the methods defined in the + * class, exposing them through the {@link MethodsMetadata} interface. + * + * @author Mark Paluch + * @since 2.1 + * @since 1.11.11 + * @see ClassMetadata + * @see MethodMetadata + * @see MethodMetadataReadingVisitor */ - @Override - public Resource getResource() { - return resource; - } + static class MethodsMetadataReadingVisitor extends AnnotationMetadataReadingVisitor implements MethodsMetadata { - /* - * (non-Javadoc) - * @see org.springframework.core.type.classreading.MetadataReader#getClassMetadata() - */ - @Override - public ClassMetadata getClassMetadata() { - return classMetadata; - } + /** + * Construct a new {@link MethodsMetadataReadingVisitor} given {@link ClassLoader}. + * + * @param classLoader may be {@literal null}. + */ + MethodsMetadataReadingVisitor(ClassLoader classLoader) { + super(classLoader); + } - /* - * (non-Javadoc) - * @see org.springframework.core.type.classreading.MetadataReader#getAnnotationMetadata() - */ - @Override - public AnnotationMetadata getAnnotationMetadata() { - return annotationMetadata; - } + /* + * (non-Javadoc) + * @see org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor#visitMethod(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[]) + */ + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - /* (non-Javadoc) - * @see org.springframework.data.util.ClassMetadataReader#getMethodsMetadata() - */ - @Override - public MethodsMetadata getMethodsMetadata() { - return methodsMetadata; + // Skip bridge methods - we're only interested in original user methods. + // On JDK 8, we'd otherwise run into double detection of the same method... + if ((access & Opcodes.ACC_BRIDGE) != 0) { + return super.visitMethod(access, name, desc, signature, exceptions); + } + + // Skip constructors + if (name.equals("")) { + return super.visitMethod(access, name, desc, signature, exceptions); + } + + MethodMetadataReadingVisitor visitor = new MethodMetadataReadingVisitor(name, access, getClassName(), + Type.getReturnType(desc).getClassName(), this.classLoader, this.methodMetadataSet); + + this.methodMetadataSet.add(visitor); + return visitor; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.util.MethodsMetadata#getMethods() + */ + @Override + public Set getMethods() { + return Collections.unmodifiableSet(methodMetadataSet); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.util.MethodsMetadata#getMethods(String) + */ + @Override + public Set getMethods(String name) { + + Assert.hasText(name, "Method name must not be null or empty"); + + Set result = new LinkedHashSet(4); + + for (MethodMetadata metadata : methodMetadataSet) { + if (metadata.getMethodName().equals(name)) { + result.add(metadata); + } + } + + return Collections.unmodifiableSet(result); + } } } diff --git a/src/main/java/org/springframework/data/type/MethodsMetadataReader.java b/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReader.java similarity index 85% rename from src/main/java/org/springframework/data/type/MethodsMetadataReader.java rename to src/main/java/org/springframework/data/type/classreading/MethodsMetadataReader.java index 7e9ce7644..9825a8995 100644 --- a/src/main/java/org/springframework/data/type/MethodsMetadataReader.java +++ b/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReader.java @@ -13,9 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.type; +package org.springframework.data.type.classreading; import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.data.type.MethodsMetadata; /** * Extension to {@link MetadataReader} for accessing class metadata and method metadata as read by an ASM @@ -28,7 +29,7 @@ import org.springframework.core.type.classreading.MetadataReader; public interface MethodsMetadataReader extends MetadataReader { /** - * @return the metadata for methods in the class file. + * @return the {@link MethodsMetadata} for methods in the class file. */ MethodsMetadata getMethodsMetadata(); } diff --git a/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReaderFactory.java b/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReaderFactory.java index 963dbf490..d3311450f 100644 --- a/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReaderFactory.java +++ b/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReaderFactory.java @@ -21,7 +21,6 @@ import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.classreading.SimpleMetadataReaderFactory; import org.springframework.data.type.MethodsMetadata; -import org.springframework.data.type.MethodsMetadataReader; /** * Extension of {@link SimpleMetadataReaderFactory} that reads {@link MethodsMetadata}, creating a new ASM diff --git a/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReadingVisitor.java b/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReadingVisitor.java deleted file mode 100644 index ea8f0a8db..000000000 --- a/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReadingVisitor.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2018 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.data.type.classreading; - -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Set; - -import org.springframework.asm.MethodVisitor; -import org.springframework.asm.Opcodes; -import org.springframework.asm.Type; -import org.springframework.core.type.ClassMetadata; -import org.springframework.core.type.MethodMetadata; -import org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor; -import org.springframework.core.type.classreading.MethodMetadataReadingVisitor; -import org.springframework.data.type.MethodsMetadata; -import org.springframework.util.Assert; - -/** - * ASM class visitor which looks for the class name and implemented types as well as for the methods defined in the - * class, exposing them through the {@link MethodsMetadata} interface. - * - * @author Mark Paluch - * @since 2.1 - * @since 1.11.11 - * @see ClassMetadata - * @see MethodMetadata - * @see MethodMetadataReadingVisitor - */ -class MethodsMetadataReadingVisitor extends AnnotationMetadataReadingVisitor implements MethodsMetadata { - - /** - * Construct a new {@link MethodsMetadataReadingVisitor} given {@link ClassLoader}. - * - * @param classLoader may be {@literal null}. - */ - MethodsMetadataReadingVisitor(ClassLoader classLoader) { - super(classLoader); - } - - /* - * (non-Javadoc) - * @see org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor#visitMethod(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[]) - */ - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - - // Skip bridge methods - we're only interested in original user methods. - // On JDK 8, we'd otherwise run into double detection of the same method... - if ((access & Opcodes.ACC_BRIDGE) != 0) { - return super.visitMethod(access, name, desc, signature, exceptions); - } - - // Skip constructors - if (name.equals("")) { - return super.visitMethod(access, name, desc, signature, exceptions); - } - - MethodMetadataReadingVisitor visitor = new MethodMetadataReadingVisitor(name, access, getClassName(), - Type.getReturnType(desc).getClassName(), this.classLoader, this.methodMetadataSet); - - this.methodMetadataSet.add(visitor); - return visitor; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.util.MethodsMetadata#getMethods() - */ - @Override - public Set getMethods() { - return Collections.unmodifiableSet(methodMetadataSet); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.util.MethodsMetadata#getMethods(String) - */ - @Override - public Set getMethods(String name) { - - Assert.hasText(name, "Method name must not be null or empty"); - - Set result = new LinkedHashSet(4); - - for (MethodMetadata metadata : methodMetadataSet) { - if (metadata.getMethodName().equals(name)) { - result.add(metadata); - } - } - - return Collections.unmodifiableSet(result); - } -} diff --git a/src/test/java/org/springframework/data/type/MethodsMetadataReaderFactoryUnitTests.java b/src/test/java/org/springframework/data/type/MethodsMetadataReaderFactoryUnitTests.java index 28707747b..d3f00e097 100644 --- a/src/test/java/org/springframework/data/type/MethodsMetadataReaderFactoryUnitTests.java +++ b/src/test/java/org/springframework/data/type/MethodsMetadataReaderFactoryUnitTests.java @@ -27,6 +27,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.data.type.classreading.MethodsMetadataReader; import org.springframework.data.type.classreading.MethodsMetadataReaderFactory; /** diff --git a/src/test/java/org/springframework/data/type/classreading/DefaultMethodsMetadataReaderUnitTests.java b/src/test/java/org/springframework/data/type/classreading/DefaultMethodsMetadataReaderUnitTests.java index 84d708f55..a1f46e516 100644 --- a/src/test/java/org/springframework/data/type/classreading/DefaultMethodsMetadataReaderUnitTests.java +++ b/src/test/java/org/springframework/data/type/classreading/DefaultMethodsMetadataReaderUnitTests.java @@ -25,7 +25,6 @@ import java.util.Set; import org.junit.Test; import org.springframework.core.type.MethodMetadata; import org.springframework.data.type.MethodsMetadata; -import org.springframework.data.type.MethodsMetadataReader; /** * Unit tests for {@link DefaultMethodsMetadataReader}.