DATACMNS-1284 - Polishing.

Backport of 5eb10a0 but leaving out the Stream execution optimizations.

Related ticket: DATACMNS-1206.
Original commit: 5eb10a0.
This commit is contained in:
Oliver Gierke
2018-04-03 10:30:34 +02:00
parent eed005427d
commit 428b0decd5
8 changed files with 90 additions and 142 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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("<init>")) {
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<MethodMetadata> getMethods() {
return Collections.unmodifiableSet(methodMetadataSet);
}
/*
* (non-Javadoc)
* @see org.springframework.data.util.MethodsMetadata#getMethods(String)
*/
@Override
public Set<MethodMetadata> getMethods(String name) {
Assert.hasText(name, "Method name must not be null or empty");
Set<MethodMetadata> result = new LinkedHashSet<MethodMetadata>(4);
for (MethodMetadata metadata : methodMetadataSet) {
if (metadata.getMethodName().equals(name)) {
result.add(metadata);
}
}
return Collections.unmodifiableSet(result);
}
}
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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("<init>")) {
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<MethodMetadata> getMethods() {
return Collections.unmodifiableSet(methodMetadataSet);
}
/*
* (non-Javadoc)
* @see org.springframework.data.util.MethodsMetadata#getMethods(String)
*/
@Override
public Set<MethodMetadata> getMethods(String name) {
Assert.hasText(name, "Method name must not be null or empty");
Set<MethodMetadata> result = new LinkedHashSet<MethodMetadata>(4);
for (MethodMetadata metadata : methodMetadataSet) {
if (metadata.getMethodName().equals(name)) {
result.add(metadata);
}
}
return Collections.unmodifiableSet(result);
}
}

View File

@@ -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;
/**

View File

@@ -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}.