|
20 | 20 |
|
21 | 21 | import java.lang.reflect.ParameterizedType;
|
22 | 22 | import java.lang.reflect.Type;
|
| 23 | +import java.lang.reflect.TypeVariable; |
23 | 24 |
|
24 |
| -import org.springframework.core.GenericTypeResolver; |
25 | 25 | import org.springframework.core.MethodParameter;
|
| 26 | +import org.springframework.core.ResolvableType; |
| 27 | +import org.springframework.lang.Nullable; |
26 | 28 |
|
27 | 29 | public interface ReturnTypeParser {
|
28 | 30 |
|
29 | 31 | default Type getReturnType(MethodParameter methodParameter) {
|
30 | 32 | if (methodParameter.getGenericParameterType() instanceof ParameterizedType)
|
31 |
| - return GenericTypeResolver.resolveType(methodParameter.getGenericParameterType(),methodParameter.getContainingClass()); |
| 33 | + return ReturnTypeParser.resolveType(methodParameter.getGenericParameterType(), methodParameter.getContainingClass()); |
32 | 34 | return methodParameter.getParameterType();
|
33 | 35 | }
|
| 36 | + |
| 37 | + /** |
| 38 | + * This is a copy of GenericTypeResolver.resolveType which is not available on spring 4. |
| 39 | + * This also keeps compatibility with spring-boot 1 applications. |
| 40 | + * Resolve the given generic type against the given context class, |
| 41 | + * substituting type variables as far as possible. |
| 42 | + * @param genericType the (potentially) generic type |
| 43 | + * @param contextClass a context class for the target type, for example a class |
| 44 | + * in which the target type appears in a method signature (can be {@code null}) |
| 45 | + * @return the resolved type (possibly the given generic type as-is) |
| 46 | + * @since 5.0 |
| 47 | + */ |
| 48 | + static Type resolveType(Type genericType, @Nullable Class<?> contextClass) { |
| 49 | + if (contextClass != null) { |
| 50 | + if (genericType instanceof TypeVariable) { |
| 51 | + ResolvableType resolvedTypeVariable = resolveVariable( |
| 52 | + (TypeVariable<?>) genericType, ResolvableType.forClass(contextClass)); |
| 53 | + if (resolvedTypeVariable != ResolvableType.NONE) { |
| 54 | + Class<?> resolved = resolvedTypeVariable.resolve(); |
| 55 | + if (resolved != null) { |
| 56 | + return resolved; |
| 57 | + } |
| 58 | + } |
| 59 | + } |
| 60 | + else if (genericType instanceof ParameterizedType) { |
| 61 | + ResolvableType resolvedType = ResolvableType.forType(genericType); |
| 62 | + if (resolvedType.hasUnresolvableGenerics()) { |
| 63 | + ParameterizedType parameterizedType = (ParameterizedType) genericType; |
| 64 | + Class<?>[] generics = new Class<?>[parameterizedType.getActualTypeArguments().length]; |
| 65 | + Type[] typeArguments = parameterizedType.getActualTypeArguments(); |
| 66 | + ResolvableType contextType = ResolvableType.forClass(contextClass); |
| 67 | + for (int i = 0; i < typeArguments.length; i++) { |
| 68 | + Type typeArgument = typeArguments[i]; |
| 69 | + if (typeArgument instanceof TypeVariable) { |
| 70 | + ResolvableType resolvedTypeArgument = resolveVariable( |
| 71 | + (TypeVariable<?>) typeArgument, contextType); |
| 72 | + if (resolvedTypeArgument != ResolvableType.NONE) { |
| 73 | + generics[i] = resolvedTypeArgument.resolve(); |
| 74 | + } |
| 75 | + else { |
| 76 | + generics[i] = ResolvableType.forType(typeArgument).resolve(); |
| 77 | + } |
| 78 | + } |
| 79 | + else { |
| 80 | + generics[i] = ResolvableType.forType(typeArgument).resolve(); |
| 81 | + } |
| 82 | + } |
| 83 | + Class<?> rawClass = resolvedType.getRawClass(); |
| 84 | + if (rawClass != null) { |
| 85 | + return ResolvableType.forClassWithGenerics(rawClass, generics).getType(); |
| 86 | + } |
| 87 | + } |
| 88 | + } |
| 89 | + } |
| 90 | + return genericType; |
| 91 | + } |
| 92 | + |
| 93 | + static ResolvableType resolveVariable(TypeVariable<?> typeVariable, ResolvableType contextType) { |
| 94 | + ResolvableType resolvedType; |
| 95 | + if (contextType.hasGenerics()) { |
| 96 | + resolvedType = ResolvableType.forType(typeVariable, contextType); |
| 97 | + if (resolvedType.resolve() != null) { |
| 98 | + return resolvedType; |
| 99 | + } |
| 100 | + } |
| 101 | + |
| 102 | + ResolvableType superType = contextType.getSuperType(); |
| 103 | + if (superType != ResolvableType.NONE) { |
| 104 | + resolvedType = resolveVariable(typeVariable, superType); |
| 105 | + if (resolvedType.resolve() != null) { |
| 106 | + return resolvedType; |
| 107 | + } |
| 108 | + } |
| 109 | + for (ResolvableType ifc : contextType.getInterfaces()) { |
| 110 | + resolvedType = resolveVariable(typeVariable, ifc); |
| 111 | + if (resolvedType.resolve() != null) { |
| 112 | + return resolvedType; |
| 113 | + } |
| 114 | + } |
| 115 | + return ResolvableType.NONE; |
| 116 | + } |
34 | 117 | }
|
35 | 118 |
|
0 commit comments