1717
1818import java .lang .annotation .Annotation ;
1919import java .lang .reflect .Method ;
20+ import java .util .ArrayList ;
21+ import java .util .Arrays ;
22+ import java .util .List ;
2023import java .util .stream .Collectors ;
2124import java .util .stream .IntStream ;
2225
2629import org .springframework .beans .factory .BeanFactory ;
2730import org .springframework .core .BridgeMethodResolver ;
2831import org .springframework .core .MethodParameter ;
32+ import org .springframework .core .ResolvableType ;
2933import org .springframework .core .annotation .AnnotatedElementUtils ;
3034import org .springframework .core .annotation .SynthesizingMethodParameter ;
3135import org .springframework .lang .Nullable ;
@@ -67,6 +71,9 @@ public class HandlerMethod {
6771
6872private final MethodParameter [] parameters ;
6973
74+ @ Nullable
75+ private volatile List <Annotation [][]> interfaceParameterAnnotations ;
76+
7077
7178/**
7279 * Constructor with a handler instance and a method.
@@ -241,6 +248,40 @@ public String getShortLogMessage() {
241248return getBeanType ().getSimpleName () + "#" + this .method .getName () + "[" + args + " args]" ;
242249}
243250
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+
244285
245286@ Override
246287public boolean equals (@ Nullable Object other ) {
@@ -323,6 +364,9 @@ protected String formatInvokeError(String text, Object[] args) {
323364 */
324365protected class HandlerMethodParameter extends SynthesizingMethodParameter {
325366
367+ @ Nullable
368+ private volatile Annotation [] combinedAnnotations ;
369+
326370public HandlerMethodParameter (int index ) {
327371super (HandlerMethod .this .bridgedMethod , index );
328372}
@@ -347,8 +391,38 @@ public <T extends Annotation> boolean hasMethodAnnotation(Class<T> annotationTyp
347391}
348392
349393@ 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 ;
352426}
353427}
354428
0 commit comments