17
17
18
18
import java .lang .annotation .Annotation ;
19
19
import java .lang .reflect .Method ;
20
+ import java .util .ArrayList ;
21
+ import java .util .Arrays ;
22
+ import java .util .List ;
20
23
import java .util .stream .Collectors ;
21
24
import java .util .stream .IntStream ;
22
25
26
29
import org .springframework .beans .factory .BeanFactory ;
27
30
import org .springframework .core .BridgeMethodResolver ;
28
31
import org .springframework .core .MethodParameter ;
32
+ import org .springframework .core .ResolvableType ;
29
33
import org .springframework .core .annotation .AnnotatedElementUtils ;
30
34
import org .springframework .core .annotation .SynthesizingMethodParameter ;
31
35
import org .springframework .lang .Nullable ;
@@ -67,6 +71,9 @@ public class HandlerMethod {
67
71
68
72
private final MethodParameter [] parameters ;
69
73
74
+ @ Nullable
75
+ private volatile List <Annotation [][]> interfaceParameterAnnotations ;
76
+
70
77
71
78
/**
72
79
* Constructor with a handler instance and a method.
@@ -241,6 +248,40 @@ public String getShortLogMessage() {
241
248
return getBeanType ().getSimpleName () + "#" + this .method .getName () + "[" + args + " args]" ;
242
249
}
243
250
251
+ private List <Annotation [][]> getInterfaceParameterAnnotations () {
252
+ List <Annotation [][]> parameterAnnotations = this .interfaceParameterAnnotations ;
253
+ if (parameterAnnotations == null ) {
254
+ parameterAnnotations = new ArrayList <>();
255
+ for (Class <?> ifc : ClassUtils .getAllInterfacesForClassAsSet (this .method .getDeclaringClass ())) {
256
+ for (Method candidate : ifc .getMethods ()) {
257
+ if (isOverrideFor (candidate )) {
258
+ parameterAnnotations .add (candidate .getParameterAnnotations ());
259
+ }
260
+ }
261
+ }
262
+ this .interfaceParameterAnnotations = parameterAnnotations ;
263
+ }
264
+ return parameterAnnotations ;
265
+ }
266
+
267
+ private boolean isOverrideFor (Method candidate ) {
268
+ if (!candidate .getName ().equals (this .method .getName ()) ||
269
+ candidate .getParameterCount () != this .method .getParameterCount ()) {
270
+ return false ;
271
+ }
272
+ Class <?>[] paramTypes = this .method .getParameterTypes ();
273
+ if (Arrays .equals (candidate .getParameterTypes (), paramTypes )) {
274
+ return true ;
275
+ }
276
+ for (int i = 0 ; i < paramTypes .length ; i ++) {
277
+ if (paramTypes [i ] !=
278
+ ResolvableType .forMethodParameter (candidate , i , this .method .getDeclaringClass ()).resolve ()) {
279
+ return false ;
280
+ }
281
+ }
282
+ return true ;
283
+ }
284
+
244
285
245
286
@ Override
246
287
public boolean equals (@ Nullable Object other ) {
@@ -323,6 +364,9 @@ protected String formatInvokeError(String text, Object[] args) {
323
364
*/
324
365
protected class HandlerMethodParameter extends SynthesizingMethodParameter {
325
366
367
+ @ Nullable
368
+ private volatile Annotation [] combinedAnnotations ;
369
+
326
370
public HandlerMethodParameter (int index ) {
327
371
super (HandlerMethod .this .bridgedMethod , index );
328
372
}
@@ -347,8 +391,38 @@ public <T extends Annotation> boolean hasMethodAnnotation(Class<T> annotationTyp
347
391
}
348
392
349
393
@ Override
350
- public HandlerMethodParameter clone () {
351
- return new HandlerMethodParameter (this );
394
+ public Annotation [] getParameterAnnotations () {
395
+ Annotation [] anns = this .combinedAnnotations ;
396
+ if (anns == null ) {
397
+ anns = super .getParameterAnnotations ();
398
+ int index = getParameterIndex ();
399
+ if (index >= 0 ) {
400
+ for (Annotation [][] ifcAnns : getInterfaceParameterAnnotations ()) {
401
+ if (index < ifcAnns .length ) {
402
+ Annotation [] paramAnns = ifcAnns [index ];
403
+ if (paramAnns .length > 0 ) {
404
+ List <Annotation > merged = new ArrayList <>(anns .length + paramAnns .length );
405
+ merged .addAll (Arrays .asList (anns ));
406
+ for (Annotation paramAnn : paramAnns ) {
407
+ boolean existingType = false ;
408
+ for (Annotation ann : anns ) {
409
+ if (ann .annotationType () == paramAnn .annotationType ()) {
410
+ existingType = true ;
411
+ break ;
412
+ }
413
+ }
414
+ if (!existingType ) {
415
+ merged .add (adaptAnnotation (paramAnn ));
416
+ }
417
+ }
418
+ anns = merged .toArray (new Annotation [0 ]);
419
+ }
420
+ }
421
+ }
422
+ }
423
+ this .combinedAnnotations = anns ;
424
+ }
425
+ return anns ;
352
426
}
353
427
}
354
428
0 commit comments