HandlerMethod exposes interface parameter annotations as well

The HandlerMethodParameter arrangement uses an approach similar to ModelAttributeMethodProcessor's FieldAwareConstructorParameter, merging the local parameter annotations with interface-declared annotations.

Issue: SPR-11055
This commit is contained in:
Juergen Hoeller
2018-07-18 17:13:55 +02:00
parent 28f7b26294
commit 790d515f8c
2 changed files with 191 additions and 2 deletions

View File

@@ -18,6 +18,9 @@ package org.springframework.web.method;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -353,6 +356,9 @@ public class HandlerMethod {
*/
protected class HandlerMethodParameter extends SynthesizingMethodParameter {
@Nullable
private volatile Annotation[] combinedAnnotations;
public HandlerMethodParameter(int index) {
super(HandlerMethod.this.bridgedMethod, index);
}
@@ -376,6 +382,42 @@ public class HandlerMethod {
return HandlerMethod.this.hasMethodAnnotation(annotationType);
}
@Override
public Annotation[] getParameterAnnotations() {
Annotation[] anns = this.combinedAnnotations;
if (anns == null) {
anns = super.getParameterAnnotations();
Class<?>[] ifcs = getDeclaringClass().getInterfaces();
for (Class<?> ifc : ifcs) {
try {
Method method = ifc.getMethod(getExecutable().getName(), getExecutable().getParameterTypes());
Annotation[] paramAnns = method.getParameterAnnotations()[getParameterIndex()];
if (paramAnns.length > 0) {
List<Annotation> merged = new ArrayList<>(anns.length + paramAnns.length);
merged.addAll(Arrays.asList(anns));
for (Annotation fieldAnn : paramAnns) {
boolean existingType = false;
for (Annotation ann : anns) {
if (ann.annotationType() == fieldAnn.annotationType()) {
existingType = true;
break;
}
}
if (!existingType) {
merged.add(fieldAnn);
}
}
anns = merged.toArray(new Annotation[0]);
}
}
catch (NoSuchMethodException ex) {
}
}
this.combinedAnnotations = anns;
}
return anns;
}
@Override
public HandlerMethodParameter clone() {
return new HandlerMethodParameter(this);