ResolvableType 泛型类型解析体系
概述
ResolvableType 是 Spring Framework 提供的泛型类型解析工具类。由于 Java 的泛型在运行期存在类型擦除(Type Erasure),无法直接在运行时获取 List<String> 中的 String 类型信息。ResolvableType 利用 Java 的 Type 体系(ParameterizedType、TypeVariable、WildcardType 等)来还原和操作泛型信息。
本文深入拆解 ResolvableType 的 10 个核心细节点,涵盖创建、解析、缓存和实际使用场景。
本文基于 Spring Framework 6.x / Spring Boot 3.x 源码分析。
1. Java Type 体系基础
1.1 接口继承关系
java.lang.reflect.Type
│
├── java.lang.Class<T> ← 原始类类型
│
├── java.lang.reflect.ParameterizedType ← 参数化类型 (List<String>)
│
├── java.lang.reflect.TypeVariable<T> ← 类型变量 (T, E, K, V)
│
├── java.lang.reflect.WildcardType ← 通配符类型 (? extends T)
│
└── java.lang.reflect.GenericArrayType ← 泛型数组类型 (T[])1.2 各类型的 Java 示例
| Type 子接口 | Java 示例 | getTypeName() |
|---|---|---|
Class | String.class | "java.lang.String" |
ParameterizedType | List<String> | "java.util.List<java.lang.String>" |
TypeVariable | T in class Foo<T> | "T" |
WildcardType | ? extends Number | "? extends java.lang.Number" |
GenericArrayType | T[] in class Foo<T> | "T[]" |
2. ResolvableType.forClass() 创建
2.1 源码
java
// ResolvableType.java
public class ResolvableType {
// 最基础的创建方式 —— 从 Class 创建
public static ResolvableType forClass(Class<?> clazz) {
// 包装为 ResolvableType,type = clazz
return new ResolvableType(clazz);
}
// 从 Class 创建并指定泛型参数
public static ResolvableType forClassWithGenerics(
Class<?> clazz, Class<?>... generics) {
// 创建 ParameterizedType 并将泛型参数绑定
// 例如: forClassWithGenerics(List.class, String.class)
// 相当于创建了 ParameterizedType(List<String>)
ResolvableType[] resolvableGenerics =
new ResolvableType[generics.length];
for (int i = 0; i < generics.length; i++) {
resolvableGenerics[i] = forClass(generics[i]);
}
return forClassWithGenerics(clazz, resolvableGenerics);
}
}2.2 使用示例
java
// 基本用法
ResolvableType t1 = ResolvableType.forClass(String.class);
// t1.getType() = String.class
// t1.resolve() = String.class
// 带泛型参数
ResolvableType t2 = ResolvableType.forClassWithGenerics(
List.class, String.class);
// t2.getType() = ParameterizedType(List<String>)
// t2.resolve() = List.class
// t2.getGeneric(0).resolve() = String.class2.3 从类字面量到 Type 的转换
java
// ResolvableType 构造器
private ResolvableType(Type type) {
this(type, null, null);
}
private ResolvableType(Type type, ResolvableTypeVariableResolver variableResolver,
ResolvableType componentType) {
// 根据 Type 的实际类型选择不同的处理方式
this.type = type;
this.variableResolver = variableResolver;
this.componentType = componentType;
// 缓存 hashCode
this.hash = calculateHash();
}3. ResolvableType.forField() 获取字段泛型
3.1 源码
java
// ResolvableType.java
public static ResolvableType forField(Field field) {
// 通过反射获取字段的泛型类型
// 利用 SerializableTypeWrapper 包装 Type 以便缓存
return forType(
SerializableTypeWrapper.forField(field),
new FieldTypeVariableResolver(field));
}
public static ResolvableType forType(Type type) {
return forType(type, null, null);
}
public static ResolvableType forType(Type type,
@Nullable ResolvableTypeVariableResolver variableResolver) {
// 检查 type 是否为 ResolvableType
if (type instanceof ResolvableType) {
return (ResolvableType) type;
}
// 创建新的 ResolvableType 实例
return new ResolvableType(type, variableResolver);
}3.2 FieldTypeVariableResolver 的作用
java
// ResolvableType.java 中的内部类
private static class FieldTypeVariableResolver
implements ResolvableTypeVariableResolver {
private final Field field;
FieldTypeVariableResolver(Field field) {
this.field = field;
}
@Override
@Nullable
public ResolvableType resolveVariable(TypeVariable<?> variable) {
// 从字段的声明类中查找类型变量的具体类型
// 例如: class MyClass<T> { T value; }
// forField(MyClass.class.getField("value"))
// 需要知道 T 的具体类型 → 从 declaringClass 的泛型参数中查找
return resolveTypeVariable(variable,
ResolvableType.forClass(this.field.getDeclaringClass()));
}
}3.3 使用示例
java
public class UserService {
private List<String> names; // 字段类型: List<String>
private Map<String, Integer> scores; // 字段类型: Map<String, Integer>
}
// 通过 ResolvableType 获取字段泛型
Field namesField = UserService.class.getDeclaredField("names");
ResolvableType resolvableType = ResolvableType.forField(namesField);
// getGeneric(0) = String.class
Class<?> genericType = resolvableType.getGeneric(0).resolve();
// genericType = String.class
// 嵌套泛型
Field scoresField = UserService.class.getDeclaredField("scores");
ResolvableType scoresType = ResolvableType.forField(scoresField);
// scoresType.getGeneric(0).resolve() = String.class
// scoresType.getGeneric(1).resolve() = Integer.class4. ResolvableType.forMethodParameter() 获取方法参数泛型
4.1 源码
java
// ResolvableType.java
public static ResolvableType forMethodParameter(MethodParameter methodParameter) {
// 从 MethodParameter 中获取方法参数的泛型类型
return forMethodParameter(methodParameter, (Class<?>) null);
}
public static ResolvableType forMethodParameter(
MethodParameter methodParameter, @Nullable Class<?> type) {
// 创建 MethodParameterTypeVariableResolver 来解析类型变量
ResolvableTypeVariableResolver resolver =
new MethodParameterTypeVariableResolver(methodParameter);
// 从 MethodParameter 获取泛型 Type
Type genericType = methodParameter.getGenericParameterType();
// 包装为 ResolvableType
return forType(
SerializableTypeWrapper.forTypeProvider(
new MethodParameterTypeProvider(methodParameter)),
resolver);
}4.2 使用示例
java
public class GenericController {
public ResponseEntity<User> getUser(Long id) {
// ResponseEntity<User> 的返回类型解析
return null;
}
public void saveUsers(List<User> users) {
// List<User> 的参数类型解析
}
}
// 解析返回类型
Method method = GenericController.class
.getMethod("getUser", Long.class);
MethodParameter returnType = MethodParameter.forExecutable(method, -1);
ResolvableType resolvableType =
ResolvableType.forMethodParameter(returnType);
// resolvableType.resolve() = ResponseEntity.class
// resolvableType.getGeneric(0).resolve() = User.class
// 解析参数类型
MethodParameter param = MethodParameter.forExecutable(method, 0);
ResolvableType paramType = ResolvableType.forMethodParameter(param);
// paramType.resolve() = List.class
// paramType.getGeneric(0).resolve() = User.class4.3 在 Spring MVC 中的应用
java
// RequestResponseBodyMethodProcessor.java 中
// 使用 ResolvableType 解析 @RequestBody 和 ResponseEntity 的泛型
@Override
protected <T> Object readWithMessageConverters(
NativeWebRequest webRequest, MethodParameter parameter,
Type paramType) {
// 从方法参数获取 ResolvableType
ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);
// 确定目标类型(用于选择 HttpMessageConverter)
Class<?> targetClass = resolvableType.resolve();
// 确定泛型参数(用于 JSON 反序列化)
ResolvableType genericType = resolvableType.getGeneric(0);
// jackson 使用 genericType 来决定 JSON 反序列化的目标类型
// 例如: List<User> → genericType = User.class → 反序列化为 User 列表
}5. ResolvableType.getGeneric(int) 获取第 N 个泛型参数
5.1 源码
java
// ResolvableType.java
public ResolvableType getGeneric(int index) {
return getGeneric(index, null, null);
}
private ResolvableType getGeneric(int index,
@Nullable ResolvableTypeVariableResolver nestedResolver,
@Nullable ResolvableType nestedComponentType) {
// 1. 获取当前类型的所有泛型参数
ResolvableType[] generics = getGenerics();
// 2. 越界检查
if (index < 0 || index >= generics.length) {
// 超出范围 → 返回 NONE(空 ResolvableType)
return ResolvableType.NONE;
}
// 3. 返回指定索引的泛型参数
ResolvableType genericType = generics[index];
// 4. 如果泛型参数本身带有嵌套变量解析器,继续包装
if (nestedResolver != null && genericType instanceof ResolvableTypeVariable) {
return forType(genericType.getType(), nestedResolver);
}
return genericType;
}5.2 getGenerics() 的内部实现
java
// ResolvableType.java
private ResolvableType[] getGenerics() {
// 懒加载 —— 缓存泛型参数数组
if (this.generics == null) {
this.generics = resolveGenerics();
}
return this.generics;
}
private ResolvableType[] resolveGenerics() {
Type type = getType();
if (type instanceof ParameterizedType) {
// ParameterizedType → 直接获取 ActualTypeArguments
Type[] typeArguments =
((ParameterizedType) type).getActualTypeArguments();
return convertToResolvableTypes(typeArguments);
}
if (type instanceof Class) {
// Class → 从类的泛型参数获取
TypeVariable<?>[] typeVariables =
((Class<?>) type).getTypeParameters();
return convertToResolvableTypes(typeVariables);
}
// 其他类型 → 空数组
return new ResolvableType[0];
}5.3 使用示例
java
// 基本泛型
ResolvableType listType = ResolvableType.forClassWithGenerics(
List.class, String.class);
listType.getGeneric(0).resolve(); // = String.class
listType.getGeneric(1).resolve(); // = null(只有一个泛型参数)
// 嵌套泛型: Map<String, List<Integer>>
ResolvableType mapType = ResolvableType.forClassWithGenerics(
Map.class,
ResolvableType.forClass(String.class),
ResolvableType.forClassWithGenerics(List.class, Integer.class));
mapType.getGeneric(0).resolve(); // = String.class
mapType.getGeneric(1).resolve(); // = List.class
mapType.getGeneric(1).getGeneric(0).resolve(); // = Integer.class
// 多层嵌套: ResponseEntity<ApiResponse<List<User>>>
ResolvableType responseType = ResolvableType.forClassWithGenerics(
ResponseEntity.class,
ResolvableType.forClassWithGenerics(
ApiResponse.class,
ResolvableType.forClassWithGenerics(
List.class, User.class)));
Class<?> userClass = responseType
.getGeneric(0) // ApiResponse<...>
.getGeneric(0) // List<User>
.getGeneric(0) // User
.resolve(); // User.class6. ResolvableType.resolve() 解析到具体类
6.1 源码
java
// ResolvableType.java
@Nullable
public Class<?> resolve() {
return resolve(this.type, this.variableResolver);
}
@Nullable
private static Class<?> resolve(Type type,
@Nullable ResolvableTypeVariableResolver variableResolver) {
// 根据 Type 的实际类型选择解析策略
if (type instanceof Class) {
// Class → 直接返回
return processResolve((Class<?>) type);
}
if (type instanceof ParameterizedType) {
// ParameterizedType → 返回 RawType
// List<String> → List.class
return resolve(((ParameterizedType) type).getRawType(),
variableResolver);
}
if (type instanceof TypeVariable) {
// TypeVariable → 尝试从 variableResolver 解析具体类型
// T → 如果 variableResolver 能解析 → 返回具体类型
// T → 如果无法解析 → 返回 Object.class
ResolvableType resolved = resolveVariable(
(TypeVariable<?>) type, variableResolver);
if (resolved != null) {
return resolved.resolve();
}
// 解析失败 → 返回 TypeVariable 的边界类型
Type[] bounds = ((TypeVariable<?>) type).getBounds();
return bounds.length > 0
? resolve(bounds[0], variableResolver)
: Object.class;
}
if (type instanceof WildcardType) {
// WildcardType → 返回上界
// ? extends Number → Number.class
// ? super Integer → Object.class(下界的上限)
Type[] upperBounds = ((WildcardType) type).getUpperBounds();
return upperBounds.length > 0
? resolve(upperBounds[0], variableResolver)
: Object.class;
}
if (type instanceof GenericArrayType) {
// GenericArrayType → 返回数组 Class
// T[] → Object[].class
GenericArrayType arrayType = (GenericArrayType) type;
Class<?> componentClass = resolve(
arrayType.getGenericComponentType(), variableResolver);
return componentClass != null
? Array.newInstance(componentClass, 0).getClass()
: Object[].class;
}
return null;
}6.2 解析示例
| 原始 Type | resolve() 结果 |
|---|---|
String.class | String.class |
ParameterizedType(List<String>) | List.class(返回 RawType) |
TypeVariable(T) — 可解析 | 具体绑定类型 |
TypeVariable(T) — 不可解析 | Object.class(边界回退) |
WildcardType(? extends Number) | Number.class |
WildcardType(? super Integer) | Object.class |
GenericArrayType(T[]) — 可解析 | String[].class |
GenericArrayType(T[]) — 不可解析 | Object[].class |
7. ResolvableType.getSuperType() 获取父类泛型
7.1 源码
java
// ResolvableType.java
public ResolvableType getSuperType() {
// 获取当前类型的父类(含泛型)
return getSuperType(null, null);
}
private ResolvableType getSuperType(
@Nullable ResolvableTypeVariableResolver nestedResolver,
@Nullable ResolvableType nestedComponentType) {
// 1. 从 type 获取父类的 Type
Type superType = resolveSuperType(this.type);
if (superType == null) {
return ResolvableType.NONE; // 没有父类(如 Object.class)
}
// 2. 包装父类为 ResolvableType
return forType(superType, new SuperTypeVariableResolver(this));
}
private Type resolveSuperType(Type type) {
if (type instanceof Class) {
// Class → 直接从 class 文件获取父类
return ((Class<?>) type).getGenericSuperclass();
}
if (type instanceof ParameterizedType) {
// ParameterizedType → 从 RawType 获取父类
Class<?> rawType = (Class<?>)
((ParameterizedType) type).getRawType();
return rawType.getGenericSuperclass();
}
return null;
}7.2 使用示例
java
public abstract class BaseRepository<T, ID> {
// 基础 CRUD 方法
}
public class UserRepository extends BaseRepository<User, Long> {
// 用户仓库实现
}
// 获取 UserRepository 的父类泛型
ResolvableType resolvableType =
ResolvableType.forClass(UserRepository.class);
// 获取父类 BaseRepository<User, Long> 的 ResolvableType
ResolvableType superType = resolvableType.getSuperType();
// superType.resolve() = BaseRepository.class
// superType.getGeneric(0).resolve() = User.class
// superType.getGeneric(1).resolve() = Long.class7.3 在 Spring Data JPA 中的应用
java
// SimpleJpaRepository.java 中
// 使用 ResolvableType.getSuperType() 获取实体类型
public class SimpleJpaRepository<T, ID> implements JpaRepository<T, ID> {
// 获取 T 的具体类型
private Class<T> getDomainClass() {
// 通过 ResolvableType 获取当前实现类的父类泛型参数
ResolvableType resolvableType =
ResolvableType.forClass(getClass())
.getSuperType(); // get Generic Superclass
// 注意:这不是实际源码,但逻辑类似
// resolvableType.getGeneric(0).resolve() = User.class
return (Class<T>) resolvableType.getGeneric(0).resolve();
}
}8. SerializableTypeWrapper 的类型缓存
8.1 源码
java
// SerializableTypeWrapper.java
public abstract class SerializableTypeWrapper {
// 底层类型缓存 —— ConcurrentReferenceHashMap
private static final ConcurrentReferenceHashMap<Type, Type> typeCache =
new ConcurrentReferenceHashMap<>(256);
// 包装 Field 的 Type
static Type forField(Field field) {
// 创建 FieldTypeProvider 来获取 Type
// 然后通过 forTypeProvider 包装
return forTypeProvider(new FieldTypeProvider(field));
}
// 核心方法:从 TypeProvider 获取 Type
static Type forTypeProvider(TypeProvider provider) {
// 1. 从 TypeProvider 获取原始 Type
Type providedType = provider.getType();
if (providedType == null || providedType instanceof Class) {
// Class 不需要缓存
return providedType;
}
// 2. 查缓存
Type cached = typeCache.get(providedType);
if (cached != null) {
return cached; // 缓存命中
}
// 3. 创建可序列化代理
// 因为 Type 本身可能不可序列化(如 sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl)
// 需要代理以支持序列化
Type serializableType = createSerializableTypeProxy(provider);
// 4. 写入缓存
typeCache.put(providedType, serializableType);
return serializableType;
}
// 创建可序列化代理
private static Type createSerializableTypeProxy(TypeProvider provider) {
// 使用 JDK 动态代理创建可序列化的 Type 实现
return (Type) Proxy.newProxyInstance(
Type.class.getClassLoader(),
new Class<?>[] { Type.class, Serializable.class },
new SerializableTypeInvocationHandler(provider));
}
}8.2 缓存的 Key 和 Value
| Key | Value | 说明 |
|---|---|---|
ParameterizedType(List<String>) | Proxy(List<String>) | JDK 代理包装的 Type |
TypeVariable(T) | Proxy(T) | 代理使其可序列化 |
WildcardType(? extends Number) | Proxy(? extends Number) | 代理使其可序列化 |
Class(String.class) | 不缓存 | Class 本身可序列化 |
8.3 缓存的目的
- 提高性能:避免重复通过反射获取
Field.getGenericType()等操作(反射调用较慢) - 支持序列化:Java 的
Type实现类(如sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl)通常不可序列化,通过 JDK 动态代理包装后支持序列化 - 类型安全:代理在
getTypeName()/toString()等调用时委托给原始 Type
9. GenericTypeResolver.resolveTypeArgument()
9.1 源码
java
// GenericTypeResolver.java
public abstract class GenericTypeResolver {
// Spring 5.x 的简化方法 —— 解析指定类的第 idx 个泛型参数
@Nullable
public static Class<?> resolveTypeArgument(
Class<?> clazz, Class<?> genericIfc) {
// 使用 ResolvableType 来实现
ResolvableType resolvableType =
ResolvableType.forClass(clazz)
.as(genericIfc);
// 如果无法解析 → 返回 null
if (resolvableType == ResolvableType.NONE) {
return null;
}
// 返回第一个泛型参数的具体类型
return resolvableType.getGeneric(0).resolve();
}
// 解析所有泛型参数
@Nullable
public static Class<?>[] resolveTypeArguments(
Class<?> clazz, Class<?> genericIfc) {
ResolvableType resolvableType =
ResolvableType.forClass(clazz).as(genericIfc);
if (resolvableType == ResolvableType.NONE
|| resolvableType.getGenerics().length == 0) {
return null;
}
// 返回所有泛型参数
ResolvableType[] generics = resolvableType.getGenerics();
Class<?>[] result = new Class<?>[generics.length];
for (int i = 0; i < generics.length; i++) {
result[i] = generics[i].resolve();
}
return result;
}
}9.2 使用示例
java
// UserRepository extends BaseRepository<User, Long>
public class UserRepository extends BaseRepository<User, Long> {}
// 解析 UserRepository 对 BaseRepository 的泛型绑定
Class<?> entityClass = GenericTypeResolver.resolveTypeArgument(
UserRepository.class, BaseRepository.class);
// entityClass = User.class
// 解析所有泛型
Class<?>[] typeArguments = GenericTypeResolver.resolveTypeArguments(
UserRepository.class, BaseRepository.class);
// typeArguments = [User.class, Long.class]9.3 Spring 5.x vs 6.x 的差异
| 版本 | 类的路径 | 推荐方式 |
|---|---|---|
| Spring 5.x | org.springframework.core.GenericTypeResolver | 推荐使用 resolveTypeArgument() |
| Spring 6.x | 同上(未废弃但标记为 @Deprecated) | 推荐直接使用 ResolvableType |
java
// Spring 6.x 推荐方式(替代 GenericTypeResolver)
Class<?> entityClass = ResolvableType
.forClass(UserRepository.class)
.as(BaseRepository.class)
.getGeneric(0)
.resolve();10. 在 Spring Boot 中的使用场景
10.1 Binder 中的类型确定
java
// Binder.java 中使用 ResolvableType 确定绑定目标类型
public <T> BindResult<T> bind(String name, Bindable<T> bindable) {
// 从 Bindable 中获取 ResolvableType
ResolvableType type = bindable.getType();
// 解析具体类型
Class<?> resolvedType = type.resolve();
if (resolvedType != null) {
// 根据具体类型执行绑定
return doBind(name, bindable);
}
return BindResult.empty();
}java
// 用户代码
@ConfigurationProperties(prefix = "app.cache")
public class CacheProperties {
private List<String> cacheNames; // ResolvableType: List<String>
private Map<String, Duration> ttl; // ResolvableType: Map<String, Duration>
}Binder 绑定时:
cacheNames 字段: ResolvableType = List<String>
→ type.resolve() = List.class
→ type.getGeneric(0).resolve() = String.class
→ 知道需要将 YAML 中的列表值绑定为 List<String>
ttl 字段: ResolvableType = Map<String, Duration>
→ type.resolve() = Map.class
→ type.getGeneric(0).resolve() = String.class
→ type.getGeneric(1).resolve() = Duration.class
→ 知道需要将值通过 ConversionService 转换为 Duration10.2 HttpMessageConverter 中的类型选择
java
// AbstractJackson2HttpMessageConverter.java
@Override
public Object read(Type type, Class<?> contextClass,
HttpInputMessage inputMessage) {
// 使用 ResolvableType 解析目标类型
ResolvableType resolvableType = ResolvableType.forType(type);
// 获取 JavaType(Jackson 类型)
JavaType javaType = getJavaType(resolvableType.getType(), contextClass);
// Jackson 根据 JavaType 确定反序列化结构
return this.objectMapper.readValue(inputMessage.getBody(), javaType);
}当 API 返回 List<User> 时:
ResolvableType = List<User>
→ getGeneric(0).resolve() = User.class
→ Jackson 创建 CollectionType(List.class, User.class)
→ 从 JSON 数组反序列化为 List<User>10.3 MvcUriComponentsBuilder 中的方法参数类型推断
java
// MvcUriComponentsBuilder.java
private static MethodParameter getMethodParameter(Method method, int paramIndex) {
MethodParameter param = new MethodParameter(method, paramIndex);
// 使用 ResolvableType 解析方法参数类型
// 特别是在泛型 Controller 中
ResolvableType resolvableType = ResolvableType
.forMethodParameter(param);
param.setParameterType(resolvableType.resolve());
return param;
}11. ResolvableTypeProvider 接口
11.1 接口定义
java
// ResolvableTypeProvider.java
@FunctionalInterface
public interface ResolvableTypeProvider {
/**
* 自定义当前实例的 ResolvableType。
* Spring 在创建 Bean 时,如果 Bean 实现了此接口,
* 会调用 getResolvableType() 来获取更精确的类型信息。
*/
ResolvableType getResolvableType();
}11.2 使用场景
java
// 场景:实现了一个通用包装类,需要让 Spring 知道内部值的泛型类型
public class GenericWrapper<T> implements ResolvableTypeProvider {
private final T value;
public GenericWrapper(T value) {
this.value = value;
}
@Override
public ResolvableType getResolvableType() {
// 让 Spring 知道 GenericWrapper<T> 中的 T 的具体类型
// 如果不实现此接口,Spring 只能看到 GenericWrapper<T> 中的 T 被视为 Object
return ResolvableType.forClassWithGenerics(
getClass(),
ResolvableType.forInstance(this.value) // 通过实例获取实际类型
);
}
public T getValue() {
return value;
}
}11.3 在 Spring 框架中使用
java
// AbstractNestablePropertyAccessor.java 中
// 获取属性值的 ResolvableType
protected ResolvableType getResolvableType(Object value) {
// 如果值实现了 ResolvableTypeProvider
if (value instanceof ResolvableTypeProvider) {
// 调用自定义的 getResolvableType()
return ((ResolvableTypeProvider) value).getResolvableType();
}
// 否则,根据值的实际类型推断
return ResolvableType.forClass(value.getClass());
}11.4 实际使用示例
java
// 不使用 ResolvableTypeProvider 时 —— 泛型信息丢失
GenericWrapper<String> wrapper = new GenericWrapper<>("hello");
ResolvableType.forInstance(wrapper).getGeneric(0).resolve();
// = Object.class ← 类型擦除导致 T 不可知
// 实现 ResolvableTypeProvider 后
public class BetterWrapper<T> implements ResolvableTypeProvider {
private final T value;
public BetterWrapper(T value) {
this.value = value;
}
@Override
public ResolvableType getResolvableType() {
return ResolvableType.forClassWithGenerics(
getClass(),
ResolvableType.forInstance(this.value) // 通过实例还原 T
);
}
}
BetterWrapper<String> wrapper = new BetterWrapper<>("hello");
ResolvableType.forInstance(wrapper).getGeneric(0).resolve();
// = String.class ← 通过 getResolvableType() 成功获取泛型信息总结
| # | 细节点 | 核心要点 |
|---|---|---|
| ① | forClass() 创建 | 从 Class 包装为 ResolvableType,支持 forClassWithGenerics() 绑定泛型参数 |
| ② | forField() 获取字段泛型 | Field.getGenericType() → FieldTypeVariableResolver 解析声明类的类型变量 |
| ③ | forMethodParameter() | MethodParameter.getGenericParameterType() → MethodParameterTypeVariableResolver |
| ④ | getGeneric(int) | 返回第 N 个泛型参数,支持嵌套 getGeneric(0).getGeneric(0) |
| ⑤ | resolve() | 消除 TypeVariable、WildcardType 等 → 返回具体 Class |
| ⑥ | getSuperType() | 获取父类的 ParameterizedType,保留父类泛型参数 |
| ⑦ | SerializableTypeWrapper | ConcurrentReferenceHashMap 缓存 Type,JDK 动态代理支持序列化 |
| ⑧ | GenericTypeResolver.resolveTypeArgument() | Spring 5.x 辅助方法,Spring 6.x 推荐直接使用 ResolvableType |
| ⑨ | Spring Boot 使用场景 | Binder 确定绑定类型、HttpMessageConverter 选择 JavaType、MvcUriComponentsBuilder 推断参数 |
| ⑩ | ResolvableTypeProvider | 实现此接口让 Spring 获取精确的泛型类型,解决类型擦除问题 |