HandlerMethod caches interface parameter annotations
Issue: SPR-11055
This commit is contained in:
parent
999c169b1c
commit
1f5d0faf1f
|
@ -29,6 +29,7 @@ import org.springframework.beans.factory.BeanFactory;
|
||||||
import org.springframework.core.BridgeMethodResolver;
|
import org.springframework.core.BridgeMethodResolver;
|
||||||
import org.springframework.core.GenericTypeResolver;
|
import org.springframework.core.GenericTypeResolver;
|
||||||
import org.springframework.core.MethodParameter;
|
import org.springframework.core.MethodParameter;
|
||||||
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
@ -81,6 +82,9 @@ public class HandlerMethod {
|
||||||
@Nullable
|
@Nullable
|
||||||
private HandlerMethod resolvedFromHandlerMethod;
|
private HandlerMethod resolvedFromHandlerMethod;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private volatile List<Annotation[][]> interfaceParameterAnnotations;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance from a bean instance and a method.
|
* Create an instance from a bean instance and a method.
|
||||||
|
@ -323,8 +327,43 @@ public class HandlerMethod {
|
||||||
* @since 4.3
|
* @since 4.3
|
||||||
*/
|
*/
|
||||||
public String getShortLogMessage() {
|
public String getShortLogMessage() {
|
||||||
int args = this.method.getParameterCount();
|
return getBeanType().getName() + "#" + this.method.getName() +
|
||||||
return getBeanType().getName() + "#" + this.method.getName() + "[" + args + " args]";
|
"[" + this.method.getParameterCount() + " args]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<Annotation[][]> getInterfaceParameterAnnotations() {
|
||||||
|
List<Annotation[][]> parameterAnnotations = this.interfaceParameterAnnotations;
|
||||||
|
if (parameterAnnotations == null) {
|
||||||
|
parameterAnnotations = new ArrayList<>();
|
||||||
|
for (Class<?> ifc : this.method.getDeclaringClass().getInterfaces()) {
|
||||||
|
for (Method candidate : ifc.getMethods()) {
|
||||||
|
if (isOverrideFor(candidate)) {
|
||||||
|
parameterAnnotations.add(candidate.getParameterAnnotations());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.interfaceParameterAnnotations = parameterAnnotations;
|
||||||
|
}
|
||||||
|
return parameterAnnotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isOverrideFor(Method candidate) {
|
||||||
|
if (!candidate.getName().equals(this.method.getName()) ||
|
||||||
|
candidate.getParameterCount() != this.method.getParameterCount()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Class<?>[] paramTypes = this.method.getParameterTypes();
|
||||||
|
if (Arrays.equals(candidate.getParameterTypes(), paramTypes)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < paramTypes.length; i++) {
|
||||||
|
if (paramTypes[i] !=
|
||||||
|
ResolvableType.forMethodParameter(candidate, i, this.method.getDeclaringClass()).resolve()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -387,30 +426,24 @@ public class HandlerMethod {
|
||||||
Annotation[] anns = this.combinedAnnotations;
|
Annotation[] anns = this.combinedAnnotations;
|
||||||
if (anns == null) {
|
if (anns == null) {
|
||||||
anns = super.getParameterAnnotations();
|
anns = super.getParameterAnnotations();
|
||||||
Class<?>[] ifcs = getDeclaringClass().getInterfaces();
|
for (Annotation[][] ifcAnns : getInterfaceParameterAnnotations()) {
|
||||||
for (Class<?> ifc : ifcs) {
|
Annotation[] paramAnns = ifcAnns[getParameterIndex()];
|
||||||
try {
|
if (paramAnns.length > 0) {
|
||||||
Method method = ifc.getMethod(getExecutable().getName(), getExecutable().getParameterTypes());
|
List<Annotation> merged = new ArrayList<>(anns.length + paramAnns.length);
|
||||||
Annotation[] paramAnns = method.getParameterAnnotations()[getParameterIndex()];
|
merged.addAll(Arrays.asList(anns));
|
||||||
if (paramAnns.length > 0) {
|
for (Annotation paramAnn : paramAnns) {
|
||||||
List<Annotation> merged = new ArrayList<>(anns.length + paramAnns.length);
|
boolean existingType = false;
|
||||||
merged.addAll(Arrays.asList(anns));
|
for (Annotation ann : anns) {
|
||||||
for (Annotation fieldAnn : paramAnns) {
|
if (ann.annotationType() == paramAnn.annotationType()) {
|
||||||
boolean existingType = false;
|
existingType = true;
|
||||||
for (Annotation ann : anns) {
|
break;
|
||||||
if (ann.annotationType() == fieldAnn.annotationType()) {
|
|
||||||
existingType = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!existingType) {
|
|
||||||
merged.add(fieldAnn);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
anns = merged.toArray(new Annotation[0]);
|
if (!existingType) {
|
||||||
|
merged.add(paramAnn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
anns = merged.toArray(new Annotation[0]);
|
||||||
catch (NoSuchMethodException ex) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.combinedAnnotations = anns;
|
this.combinedAnnotations = anns;
|
||||||
|
|
Loading…
Reference in New Issue