diff --git a/spring-aop/src/main/java/org/springframework/aop/support/AopUtils.java b/spring-aop/src/main/java/org/springframework/aop/support/AopUtils.java
index 83358da1594b..01734d3bab83 100644
--- a/spring-aop/src/main/java/org/springframework/aop/support/AopUtils.java
+++ b/spring-aop/src/main/java/org/springframework/aop/support/AopUtils.java
@@ -193,6 +193,12 @@ public static boolean isFinalizeMethod(@Nullable Method method) {
*/
public static Method getMostSpecificMethod(Method method, @Nullable Class> targetClass) {
Class> specificTargetClass = (targetClass != null ? ClassUtils.getUserClass(targetClass) : null);
+ Class>[] interfaces = targetClass.getInterfaces();
+ for (Class> itf : interfaces) {
+ Method mostSpecificMethod = getMostSpecificMethod(method, itf);
+ if (!method.equals(mostSpecificMethod))
+ return mostSpecificMethod;
+ }
Method resolvedMethod = ClassUtils.getMostSpecificMethod(method, specificTargetClass);
// If we are dealing with method with generic parameters, find the original method.
return BridgeMethodResolver.findBridgedMethod(resolvedMethod);
diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java
index c8982c81a74e..bfcee21d6efa 100644
--- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java
+++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java
@@ -556,7 +556,7 @@ public static A findAnnotation(Method method, @Nullable C
}
@Nullable
- private static A searchOnInterfaces(Method method, Class annotationType, Class>... ifcs) {
+ public static A searchOnInterfaces(Method method, Class annotationType, Class>... ifcs) {
for (Class> ifc : ifcs) {
Set annotatedMethods = getAnnotatedMethodsInBaseType(ifc);
if (!annotatedMethods.isEmpty()) {
diff --git a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java
index 0ae0c1f5eec1..842f23a3c3ce 100644
--- a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java
+++ b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java
@@ -336,6 +336,13 @@ private List getInterfaceParameterAnnotations() {
List parameterAnnotations = this.interfaceParameterAnnotations;
if (parameterAnnotations == null) {
parameterAnnotations = new ArrayList<>();
+ for (Class> ifc : this.beanType.getInterfaces()) {
+ for (Method candidate : ifc.getMethods()) {
+ if (isOverrideFor(candidate)) {
+ parameterAnnotations.add(candidate.getParameterAnnotations());
+ }
+ }
+ }
for (Class> ifc : this.method.getDeclaringClass().getInterfaces()) {
for (Method candidate : ifc.getMethods()) {
if (isOverrideFor(candidate)) {
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java
index 6289027d4dec..4b4877e2fa99 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java
@@ -218,6 +218,9 @@ protected boolean isHandler(Class> beanType) {
@Nullable
protected RequestMappingInfo getMappingForMethod(Method method, Class> handlerType) {
RequestMappingInfo info = createRequestMappingInfo(method);
+ if (info == null) {
+ info = createRequestMappingInfo(method, handlerType.getInterfaces());
+ }
if (info != null) {
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {