Skip to content

Commit 57d9801

Browse files
committed
Avoid mismatch between cached top-level versus nested parameter type
Issue: SPR-13755 (cherry picked from commit c909789)
1 parent ff8bbc9 commit 57d9801

File tree

2 files changed

+36
-25
lines changed

2 files changed

+36
-25
lines changed

spring-core/src/main/java/org/springframework/core/GenericTypeResolver.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -51,28 +51,28 @@ public abstract class GenericTypeResolver {
5151

5252
/**
5353
* Determine the target type for the given parameter specification.
54-
* @param methodParam the method parameter specification
54+
* @param methodParameter the method parameter specification
5555
* @return the corresponding generic parameter type
5656
* @deprecated as of Spring 4.0, use {@link MethodParameter#getGenericParameterType()}
5757
*/
5858
@Deprecated
59-
public static Type getTargetType(MethodParameter methodParam) {
60-
Assert.notNull(methodParam, "MethodParameter must not be null");
61-
return methodParam.getGenericParameterType();
59+
public static Type getTargetType(MethodParameter methodParameter) {
60+
Assert.notNull(methodParameter, "MethodParameter must not be null");
61+
return methodParameter.getGenericParameterType();
6262
}
6363

6464
/**
6565
* Determine the target type for the given generic parameter type.
66-
* @param methodParam the method parameter specification
67-
* @param clazz the class to resolve type variables against
66+
* @param methodParameter the method parameter specification
67+
* @param implementationClass the class to resolve type variables against
6868
* @return the corresponding generic parameter or return type
6969
*/
70-
public static Class<?> resolveParameterType(MethodParameter methodParam, Class<?> clazz) {
71-
Assert.notNull(methodParam, "MethodParameter must not be null");
72-
Assert.notNull(clazz, "Class must not be null");
73-
methodParam.setContainingClass(clazz);
74-
methodParam.setParameterType(ResolvableType.forMethodParameter(methodParam).resolve());
75-
return methodParam.getParameterType();
70+
public static Class<?> resolveParameterType(MethodParameter methodParameter, Class<?> implementationClass) {
71+
Assert.notNull(methodParameter, "MethodParameter must not be null");
72+
Assert.notNull(implementationClass, "Class must not be null");
73+
methodParameter.setContainingClass(implementationClass);
74+
ResolvableType.resolveMethodParameter(methodParameter);
75+
return methodParameter.getParameterType();
7676
}
7777

7878
/**

spring-core/src/main/java/org/springframework/core/ResolvableType.java

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,7 @@ public ResolvableType getSuperType() {
381381
return NONE;
382382
}
383383
if (this.superType == null) {
384-
this.superType = forType(SerializableTypeWrapper.forGenericSuperclass(resolved),
385-
asVariableResolver());
384+
this.superType = forType(SerializableTypeWrapper.forGenericSuperclass(resolved), asVariableResolver());
386385
}
387386
return this.superType;
388387
}
@@ -399,8 +398,7 @@ public ResolvableType[] getInterfaces() {
399398
return EMPTY_TYPES_ARRAY;
400399
}
401400
if (this.interfaces == null) {
402-
this.interfaces = forTypes(SerializableTypeWrapper.forGenericInterfaces(resolved),
403-
asVariableResolver());
401+
this.interfaces = forTypes(SerializableTypeWrapper.forGenericInterfaces(resolved), asVariableResolver());
404402
}
405403
return this.interfaces;
406404
}
@@ -1102,11 +1100,11 @@ public static ResolvableType forMethodParameter(MethodParameter methodParameter)
11021100
*/
11031101
public static ResolvableType forMethodParameter(MethodParameter methodParameter, ResolvableType implementationType) {
11041102
Assert.notNull(methodParameter, "MethodParameter must not be null");
1105-
implementationType = (implementationType == null ? forType(methodParameter.getContainingClass()) : implementationType);
1103+
implementationType = (implementationType != null ? implementationType :
1104+
forType(methodParameter.getContainingClass()));
11061105
ResolvableType owner = implementationType.as(methodParameter.getDeclaringClass());
1107-
return forType(null, new MethodParameterTypeProvider(methodParameter),
1108-
owner.asVariableResolver()).getNested(methodParameter.getNestingLevel(),
1109-
methodParameter.typeIndexesPerLevel);
1106+
return forType(null, new MethodParameterTypeProvider(methodParameter), owner.asVariableResolver()).
1107+
getNested(methodParameter.getNestingLevel(), methodParameter.typeIndexesPerLevel);
11101108
}
11111109

11121110
/**
@@ -1124,13 +1122,26 @@ public static ResolvableType forMethodParameter(MethodParameter methodParameter,
11241122
getNested(methodParameter.getNestingLevel(), methodParameter.typeIndexesPerLevel);
11251123
}
11261124

1125+
/**
1126+
* Resolve the top-level parameter type of the given {@code MethodParameter}.
1127+
* @param methodParameter the method parameter to resolve
1128+
* @since 4.1.9
1129+
* @see MethodParameter#setParameterType
1130+
*/
1131+
static void resolveMethodParameter(MethodParameter methodParameter) {
1132+
Assert.notNull(methodParameter, "MethodParameter must not be null");
1133+
ResolvableType owner = forType(methodParameter.getContainingClass()).as(methodParameter.getDeclaringClass());
1134+
methodParameter.setParameterType(
1135+
forType(null, new MethodParameterTypeProvider(methodParameter), owner.asVariableResolver()).resolve());
1136+
}
1137+
11271138
/**
11281139
* Return a {@link ResolvableType} as a array of the specified {@code componentType}.
11291140
* @param componentType the component type
11301141
* @return a {@link ResolvableType} as an array of the specified component type
11311142
*/
11321143
public static ResolvableType forArrayComponent(ResolvableType componentType) {
1133-
Assert.notNull(componentType, "componentType must not be null");
1144+
Assert.notNull(componentType, "Component type must not be null");
11341145
Class<?> arrayClass = Array.newInstance(componentType.resolve(), 0).getClass();
11351146
return new ResolvableType(arrayClass, null, null, componentType);
11361147
}
@@ -1220,7 +1231,7 @@ static ResolvableType forType(Type type, TypeProvider typeProvider, VariableReso
12201231
/**
12211232
* Strategy interface used to resolve {@link TypeVariable}s.
12221233
*/
1223-
static interface VariableResolver extends Serializable {
1234+
interface VariableResolver extends Serializable {
12241235

12251236
/**
12261237
* Return the source of the resolver (used for hashCode and equals).
@@ -1230,7 +1241,7 @@ static interface VariableResolver extends Serializable {
12301241
/**
12311242
* Resolve the specified variable.
12321243
* @param variable the variable to resolve
1233-
* @return the resolved variable or {@code null}
1244+
* @return the resolved variable, or {@code null} if not found
12341245
*/
12351246
ResolvableType resolveVariable(TypeVariable<?> variable);
12361247
}
@@ -1362,7 +1373,7 @@ public static WildcardBounds get(ResolvableType type) {
13621373
/**
13631374
* The various kinds of bounds.
13641375
*/
1365-
static enum Kind {UPPER, LOWER}
1376+
enum Kind {UPPER, LOWER}
13661377
}
13671378

13681379
}

0 commit comments

Comments
 (0)