How to Elegantly Retrieve Generic Types in Spring with ResolvableType
This article explains how to extract generic type information in Spring, first by manually parsing class hierarchies with reflection and then using Spring 4's ResolvableType utility, providing code examples and API references for fields, methods, constructors, and instances.
Introduction
Spring's source code is a treasure trove; many tools can be found there. The author's open-source project mica is built entirely on Spring for basic enhancements without reinventing the wheel. This article shows how to obtain generic types gracefully in Spring.
Getting Generic Types
Manual parsing
The previous approach, derived from vjtools, uses reflection to read the generic parameter declared on a superclass.
/**
* 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
* 注意泛型必须定义在父类处. 这是唯一可以通过反射从泛型获得Class实例的地方.
* 如无法找到, 返回Object.class.
* 如public UserDao extends HibernateDao<User,Long>
* @param clazz clazz The class to introspect
* @param index the Index of the generic declaration, start from 0.
* @return the index generic declaration, or Object.class if cannot be determined
*/
public static Class getClassGenericType(final Class clazz, final int index) {
Type genType = clazz.getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if ((index >= params.length) || (index < 0)) {
logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " + params.length);
return Object.class;
}
if (!(params[index] instanceof Class)) {
logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
return Object.class;
}
return (Class) params[index];
}ResolvableType utility
Since Spring 4.0, the ResolvableType class simplifies generic type retrieval. The official example demonstrates its usage:
private HashMap<Integer, List<String>> myMap;
public void example() {
ResolvableType t = ResolvableType.forField(getClass().getDeclaredField("myMap"));
t.getSuperType(); // AbstractMap<Integer, List<String>>
t.asMap(); // Map<Integer, List<String>>
t.getGeneric(0).resolve(); // Integer
t.getGeneric(1).resolve(); // List
t.getGeneric(1); // List<String>
t.resolveGeneric(1, 0); // String
}Detailed usage
Obtain generic information from a Field
ResolvableType.forField(Field)Obtain generic information from a Method parameter
ResolvableType.forMethodParameter(Method, int)Obtain generic information from a Method return type
ResolvableType.forMethodReturnType(Method)Obtain generic information from a Constructor parameter
ResolvableType.forConstructorParameter(Constructor, int)Obtain generic information from a Class
ResolvableType.forClass(Class)Obtain generic information from a Type
ResolvableType.forType(Type)Obtain generic information from an instance
ResolvableType.forInstance(Object)For more API details, see the ResolvableType Javadoc: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/ResolvableType.html
References
[1]mica: https://gitee.com/596392912/mica [2] Spring ResolvableType Javadoc: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/ResolvableType.html
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Architecture Diary
Committed to sharing original, high‑quality technical articles; no fluff or promotional content.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
