Skip to content

Commit 1f5d0fa

Browse files
committed
HandlerMethod caches interface parameter annotations
Issue: SPR-11055
1 parent 999c169 commit 1f5d0fa

File tree

1 file changed

+56
-23
lines changed

1 file changed

+56
-23
lines changed

spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.springframework.core.BridgeMethodResolver;
3030
import org.springframework.core.GenericTypeResolver;
3131
import org.springframework.core.MethodParameter;
32+
import org.springframework.core.ResolvableType;
3233
import org.springframework.core.annotation.AnnotatedElementUtils;
3334
import org.springframework.core.annotation.SynthesizingMethodParameter;
3435
import org.springframework.http.HttpStatus;
@@ -81,6 +82,9 @@ public class HandlerMethod {
8182
@Nullable
8283
private HandlerMethod resolvedFromHandlerMethod;
8384

85+
@Nullable
86+
private volatile List<Annotation[][]> interfaceParameterAnnotations;
87+
8488

8589
/**
8690
* Create an instance from a bean instance and a method.
@@ -323,8 +327,43 @@ public HandlerMethod createWithResolvedBean() {
323327
* @since 4.3
324328
*/
325329
public String getShortLogMessage() {
326-
int args = this.method.getParameterCount();
327-
return getBeanType().getName() + "#" + this.method.getName() + "[" + args + " args]";
330+
return getBeanType().getName() + "#" + this.method.getName() +
331+
"[" + this.method.getParameterCount() + " args]";
332+
}
333+
334+
335+
private List<Annotation[][]> getInterfaceParameterAnnotations() {
336+
List<Annotation[][]> parameterAnnotations = this.interfaceParameterAnnotations;
337+
if (parameterAnnotations == null) {
338+
parameterAnnotations = new ArrayList<>();
339+
for (Class<?> ifc : this.method.getDeclaringClass().getInterfaces()) {
340+
for (Method candidate : ifc.getMethods()) {
341+
if (isOverrideFor(candidate)) {
342+
parameterAnnotations.add(candidate.getParameterAnnotations());
343+
}
344+
}
345+
}
346+
this.interfaceParameterAnnotations = parameterAnnotations;
347+
}
348+
return parameterAnnotations;
349+
}
350+
351+
private boolean isOverrideFor(Method candidate) {
352+
if (!candidate.getName().equals(this.method.getName()) ||
353+
candidate.getParameterCount() != this.method.getParameterCount()) {
354+
return false;
355+
}
356+
Class<?>[] paramTypes = this.method.getParameterTypes();
357+
if (Arrays.equals(candidate.getParameterTypes(), paramTypes)) {
358+
return true;
359+
}
360+
for (int i = 0; i < paramTypes.length; i++) {
361+
if (paramTypes[i] !=
362+
ResolvableType.forMethodParameter(candidate, i, this.method.getDeclaringClass()).resolve()) {
363+
return false;
364+
}
365+
}
366+
return true;
328367
}
329368

330369

@@ -387,30 +426,24 @@ public Annotation[] getParameterAnnotations() {
387426
Annotation[] anns = this.combinedAnnotations;
388427
if (anns == null) {
389428
anns = super.getParameterAnnotations();
390-
Class<?>[] ifcs = getDeclaringClass().getInterfaces();
391-
for (Class<?> ifc : ifcs) {
392-
try {
393-
Method method = ifc.getMethod(getExecutable().getName(), getExecutable().getParameterTypes());
394-
Annotation[] paramAnns = method.getParameterAnnotations()[getParameterIndex()];
395-
if (paramAnns.length > 0) {
396-
List<Annotation> merged = new ArrayList<>(anns.length + paramAnns.length);
397-
merged.addAll(Arrays.asList(anns));
398-
for (Annotation fieldAnn : paramAnns) {
399-
boolean existingType = false;
400-
for (Annotation ann : anns) {
401-
if (ann.annotationType() == fieldAnn.annotationType()) {
402-
existingType = true;
403-
break;
404-
}
405-
}
406-
if (!existingType) {
407-
merged.add(fieldAnn);
429+
for (Annotation[][] ifcAnns : getInterfaceParameterAnnotations()) {
430+
Annotation[] paramAnns = ifcAnns[getParameterIndex()];
431+
if (paramAnns.length > 0) {
432+
List<Annotation> merged = new ArrayList<>(anns.length + paramAnns.length);
433+
merged.addAll(Arrays.asList(anns));
434+
for (Annotation paramAnn : paramAnns) {
435+
boolean existingType = false;
436+
for (Annotation ann : anns) {
437+
if (ann.annotationType() == paramAnn.annotationType()) {
438+
existingType = true;
439+
break;
408440
}
409441
}
410-
anns = merged.toArray(new Annotation[0]);
442+
if (!existingType) {
443+
merged.add(paramAnn);
444+
}
411445
}
412-
}
413-
catch (NoSuchMethodException ex) {
446+
anns = merged.toArray(new Annotation[0]);
414447
}
415448
}
416449
this.combinedAnnotations = anns;

0 commit comments

Comments
 (0)