Elegant Method of Getting Generic Information in Spring

  • 2021-07-10 19:58:26
  • OfStack

Brief introduction

Spring source code is a big treasure house, we can meet most tools can be found in the source code, so the author's open source mica is completely based on Spring for basic enhancement, and does not repeat wheels. What I want to share today is the elegant acquisition of generics in Spring.

Get generics

Self-analysis

Our previous processing method, the code source is vjtools (Jiangnan White).


/**
 *  Through reflection ,  Obtain Class The type of generic parameter of the parent class declared in the definition .
 * 
 *  Note that generics must be defined at the parent class .  This is the only 1 Can be obtained from generics through reflection Class The place of the instance .
 * 
 *  If it cannot be found ,  Return Object.class.
 * 
 *  Such as 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 Tools

Since Spring 4.0, ResolvableType tool has been added to Spring, which makes it easier to return generic information.
First, let's look at the official example:


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 description

Construct to get generic information of Field


ResolvableType.forField(Field)

Construct to get generic information of Method


ResolvableType.forMethodParameter(Method, int)

Construct to get generic information of parameters returned by methods


ResolvableType.forMethodReturnType(Method)

Construct to get generic information of construction parameters


ResolvableType.forConstructorParameter(Constructor, int)

Construct to get generic information of a class


ResolvableType.forClass(Class)

Construct to get generic information of a type


ResolvableType.forType(Type)

Construct to get generic information of an instance


ResolvableType.forInstance(Object)

For more use of Api, please see ResolvableType java doc: https://docs.spring.io/spring-framework/docs/current/api/org/springframework/core/ResolvableType.html


Related articles: