From 5708b73ea9a6dd370f79a3989b33af17773bf501 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Thu, 26 Mar 2026 15:54:25 +0100 Subject: [PATCH] Introduce ResolvableType.forParameter() factory method Prior to this commit, one could invoke ResolvableType.forMethodParameter(MethodParameter.forParameter(parameter)) to create a ResolvableType for a Parameter; however, that's slightly cumbersome. To address that, this commit introduces ResolvableType.forParameter(), analogous to existing convenience factory methods in ResolvableType. Closes gh-36545 --- .../springframework/core/MethodParameter.java | 1 + .../springframework/core/ResolvableType.java | 13 ++++++++++ .../core/ResolvableTypeTests.java | 24 +++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/spring-core/src/main/java/org/springframework/core/MethodParameter.java b/spring-core/src/main/java/org/springframework/core/MethodParameter.java index 79fff8944cf..c55b9805180 100644 --- a/spring-core/src/main/java/org/springframework/core/MethodParameter.java +++ b/spring-core/src/main/java/org/springframework/core/MethodParameter.java @@ -822,6 +822,7 @@ public class MethodParameter { * @since 5.0 */ public static MethodParameter forParameter(Parameter parameter) { + Assert.notNull(parameter, "Parameter must not be null"); return forExecutable(parameter.getDeclaringExecutable(), findParameterIndex(parameter)); } diff --git a/spring-core/src/main/java/org/springframework/core/ResolvableType.java b/spring-core/src/main/java/org/springframework/core/ResolvableType.java index e053cd3998a..9273abd4d11 100644 --- a/spring-core/src/main/java/org/springframework/core/ResolvableType.java +++ b/spring-core/src/main/java/org/springframework/core/ResolvableType.java @@ -22,6 +22,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Method; +import java.lang.reflect.Parameter; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; @@ -1280,6 +1281,18 @@ public class ResolvableType implements Serializable { return forType(null, new FieldTypeProvider(field), owner.asVariableResolver()).getNested(nestingLevel); } + /** + * Return a {@code ResolvableType} for the specified {@link Parameter}. + *

This is a convenience factory method for scenarios where a {@code Parameter} + * descriptor is already available. + * @param parameter the source parameter + * @return a {@code ResolvableType} for the specified parameter + * @since 7.1 + */ + public static ResolvableType forParameter(Parameter parameter) { + return forMethodParameter(MethodParameter.forParameter(parameter)); + } + /** * Return a {@code ResolvableType} for the specified {@link Constructor} parameter. * @param constructor the source constructor (must not be {@code null}) diff --git a/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java b/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java index 40d69967b3a..6e07060249a 100644 --- a/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java +++ b/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java @@ -25,6 +25,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Method; +import java.lang.reflect.Parameter; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; @@ -207,6 +208,29 @@ class ResolvableTypeTests { .withMessage("Field must not be null"); } + @Test + void forParameterForMethod() throws Exception { + Method method = Methods.class.getMethod("charSequenceParameter", List.class); + Parameter parameter = method.getParameters()[0]; + ResolvableType type = ResolvableType.forParameter(parameter); + assertThat(type.getType()).isEqualTo(method.getGenericParameterTypes()[0]); + } + + @Test + void forParameterForConstructor() throws Exception { + Constructor constructor = Constructors.class.getConstructor(List.class); + Parameter parameter = constructor.getParameters()[0]; + ResolvableType type = ResolvableType.forParameter(parameter); + assertThat(type.getType()).isEqualTo(constructor.getGenericParameterTypes()[0]); + } + + @Test + void forParameterMustNotBeNull() { + assertThatIllegalArgumentException() + .isThrownBy(() -> ResolvableType.forParameter(null)) + .withMessage("Parameter must not be null"); + } + @Test void forConstructorParameter() throws Exception { Constructor constructor = Constructors.class.getConstructor(List.class);