【深入理解MyBatis】- 08Mybatis 类型封装TypeParameterResolver

基本使用

TypeParameterResolver能做什么?

  • 获取字段的类型,如String name;中的String
  • 获取方法返回值类型,如Double simpleSelect();中的Double
  • 获取方法入参类型,如void simpleSelectVoid(Integer param);中的Integer

基本使用例子

import static org.junit.Assert.assertEquals;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

import org.junit.Test;

public class MyTypeParameterResolverTest {
	
	static class Person {
		private String name;
		
		String test(Integer n) {
			return name;
		}
	}
	
	@Test
	public void testReturn_String() throws Exception {
		Class<?> clazz = Person.class;
		Method method = clazz.getDeclaredMethod("test", Integer.class);
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertEquals(String.class, result);
	}
	
	@Test
	public void testParam_Integer() throws Exception {
		Class<?> clazz = Person.class;
		Method method = clazz.getDeclaredMethod("test", Integer.class);
		Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
		assertEquals(Integer.class, result[0]);
	}
	
	@Test
	public void testField_String() throws Exception {
		Class<?> clazz = Person.class;
		Field field = clazz.getDeclaredField("name");
		Type result = TypeParameterResolver.resolveFieldType(field, clazz);
		assertEquals(String.class, result);
	}
}

获取复杂类型参数

包括java type

  • ParameterizedType
  • TypeVariable
  • GenericArrayType
  • WildcardType

使用如下

public class TypeParameterResolverTest {
	@Test
	public void testReturn_Lv0SimpleClass() throws Exception {
		// Double simpleSelect();
		Class<?> clazz = Level0Mapper.class;
		Method method = clazz.getMethod("simpleSelect");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertEquals(Double.class, result);
	}

	@Test
	public void testReturn_SimpleVoid() throws Exception {
		// void simpleSelectVoid(Integer param);
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("simpleSelectVoid", Integer.class);
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertEquals(void.class, result);
	}

	@Test
	public void testReturn_SimplePrimitive() throws Exception {
		// double simpleSelectPrimitive(int param);
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("simpleSelectPrimitive", int.class);
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertEquals(double.class, result);
	}

	@Test
	public void testReturn_SimpleClass() throws Exception {
		// Double simpleSelect();
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("simpleSelect");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertEquals(Double.class, result);
	}

	@Test
	public void testReturn_SimpleList() throws Exception {
		// List<Double> simpleSelectList();
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("simpleSelectList");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertTrue(result instanceof ParameterizedType);
		ParameterizedType paramType = (ParameterizedType) result;
		assertEquals(List.class, paramType.getRawType());
		assertEquals(1, paramType.getActualTypeArguments().length);
		assertEquals(Double.class, paramType.getActualTypeArguments()[0]);
	}

	@Test
	public void testReturn_SimpleMap() throws Exception {
		// Map<Integer, Double> simpleSelectMap();
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("simpleSelectMap");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertTrue(result instanceof ParameterizedType);
		ParameterizedType paramType = (ParameterizedType) result;
		assertEquals(Map.class, paramType.getRawType());
		assertEquals(2, paramType.getActualTypeArguments().length);
		assertEquals(Integer.class, paramType.getActualTypeArguments()[0]);
		assertEquals(Double.class, paramType.getActualTypeArguments()[1]);
	}

	@Test
	public void testReturn_SimpleWildcard() throws Exception {
		// List<? extends String> simpleSelectWildcard();
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("simpleSelectWildcard");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertTrue(result instanceof ParameterizedType);
		ParameterizedType paramType = (ParameterizedType) result;
		assertEquals(List.class, paramType.getRawType());
		assertEquals(1, paramType.getActualTypeArguments().length);
		assertTrue(paramType.getActualTypeArguments()[0] instanceof WildcardType);
		WildcardType wildcard = (WildcardType) paramType.getActualTypeArguments()[0];
		assertEquals(String.class, wildcard.getUpperBounds()[0]);
	}

	@Test
	public void testReturn_SimpleArray() throws Exception {
		// String[] simpleSelectArray();
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("simpleSelectArray");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertTrue(result instanceof Class);
		Class<?> resultClass = (Class<?>) result;
		assertTrue(resultClass.isArray());
		assertEquals(String.class, resultClass.getComponentType());
	}

	@Test
	public void testReturn_SimpleArrayOfArray() throws Exception {
		// String[][] simpleSelectArrayOfArray();
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("simpleSelectArrayOfArray");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertTrue(result instanceof Class);
		Class<?> resultClass = (Class<?>) result;
		assertTrue(resultClass.isArray());
		assertTrue(resultClass.getComponentType().isArray());
		assertEquals(String.class, resultClass.getComponentType().getComponentType());
	}

	@Test
	public void testReturn_SimpleTypeVar() throws Exception {
		// <K extends Calculator<?>> K simpleSelectTypeVar();
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("simpleSelectTypeVar");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertEquals(Object.class, result);
	}

	@Test
	public void testReturn_Lv1Class() throws Exception {
		// N select(N param);
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("select", Object.class);
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertEquals(String.class, result);
	}

	@Test
	public void testReturn_Lv2CustomClass() throws Exception {
		// Calculator<N> selectCalculator(Calculator<N> param);
		Class<?> clazz = Level2Mapper.class;
		Method method = clazz.getMethod("selectCalculator", Calculator.class);
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertTrue(result instanceof ParameterizedType);
		ParameterizedType paramType = (ParameterizedType) result;
		assertEquals(Calculator.class, paramType.getRawType());
		assertEquals(1, paramType.getActualTypeArguments().length);
		assertEquals(String.class, paramType.getActualTypeArguments()[0]);
	}

	@Test
	public void testReturn_Lv2CustomClassList() throws Exception {
		// List<Calculator<L>> selectCalculatorList();
		Class<?> clazz = Level2Mapper.class;
		Method method = clazz.getMethod("selectCalculatorList");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertTrue(result instanceof ParameterizedType);
		ParameterizedType paramTypeOuter = (ParameterizedType) result;
		assertEquals(List.class, paramTypeOuter.getRawType());
		assertEquals(1, paramTypeOuter.getActualTypeArguments().length);
		ParameterizedType paramTypeInner = (ParameterizedType) paramTypeOuter.getActualTypeArguments()[0];
		assertEquals(Calculator.class, paramTypeInner.getRawType());
		assertEquals(Date.class, paramTypeInner.getActualTypeArguments()[0]);
	}

	@Test
	public void testReturn_Lv0InnerClass() throws Exception {
		// N select(N param);
		Class<?> clazz = Level0InnerMapper.class;
		Method method = clazz.getMethod("select", Object.class);
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertEquals(Float.class, result);
	}

	@Test
	public void testReturn_Lv2Class() throws Exception {
		// N select(N param);
		Class<?> clazz = Level2Mapper.class;
		Method method = clazz.getMethod("select", Object.class);
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertEquals(String.class, result);
	}

	@Test
	public void testReturn_Lv1List() throws Exception {
		// List<N> selectList(M param1, N param2);
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("selectList", Object.class, Object.class);
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertTrue(result instanceof ParameterizedType);
		ParameterizedType type = (ParameterizedType) result;
		assertEquals(List.class, type.getRawType());
		assertEquals(1, type.getActualTypeArguments().length);
		assertEquals(String.class, type.getActualTypeArguments()[0]);
	}

	@Test
	public void testReturn_Lv1Array() throws Exception {
		// N[] selectArray(List<N>[] param);
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("selectArray", List[].class);
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertTrue(result instanceof Class);
		Class<?> resultClass = (Class<?>) result;
		assertTrue(resultClass.isArray());
		assertEquals(String.class, resultClass.getComponentType());
	}

	@Test
	public void testReturn_Lv2ArrayOfArray() throws Exception {
		// N[][] selectArrayOfArray();
		Class<?> clazz = Level2Mapper.class;
		Method method = clazz.getMethod("selectArrayOfArray");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertTrue(result instanceof Class);
		Class<?> resultClass = (Class<?>) result;
		assertTrue(result instanceof Class);
		assertTrue(resultClass.isArray());
		assertTrue(resultClass.getComponentType().isArray());
		assertEquals(String.class, resultClass.getComponentType().getComponentType());
	}

	@Test
	public void testReturn_Lv2ArrayOfList() throws Exception {
		//  List<N>[] selectArrayOfList();
		Class<?> clazz = Level2Mapper.class;
		Method method = clazz.getMethod("selectArrayOfList");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertTrue(result instanceof GenericArrayType);
		GenericArrayType genericArrayType = (GenericArrayType) result;
		assertTrue(genericArrayType.getGenericComponentType() instanceof ParameterizedType);
		ParameterizedType paramType = (ParameterizedType) genericArrayType.getGenericComponentType();
		assertEquals(List.class, paramType.getRawType());
		assertEquals(String.class, paramType.getActualTypeArguments()[0]);
	}

	@Test
	public void testReturn_Lv2WildcardList() throws Exception {
		// List<? extends N> selectWildcardList();
		Class<?> clazz = Level2Mapper.class;
		Method method = clazz.getMethod("selectWildcardList");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertTrue(result instanceof ParameterizedType);
		ParameterizedType type = (ParameterizedType) result;
		assertEquals(List.class, type.getRawType());
		assertEquals(1, type.getActualTypeArguments().length);
		assertTrue(type.getActualTypeArguments()[0] instanceof WildcardType);
		WildcardType wildcard = (WildcardType) type.getActualTypeArguments()[0];
		assertEquals(0, wildcard.getLowerBounds().length);
		assertEquals(1, wildcard.getUpperBounds().length);
		assertEquals(String.class, wildcard.getUpperBounds()[0]);
	}

	@Test
	public void testReturn_LV2Map() throws Exception {
		// Map<N, M> selectMap();
		Class<?> clazz = Level2Mapper.class;
		Method method = clazz.getMethod("selectMap");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertTrue(result instanceof ParameterizedType);
		ParameterizedType paramType = (ParameterizedType) result;
		assertEquals(Map.class, paramType.getRawType());
		assertEquals(2, paramType.getActualTypeArguments().length);
		assertEquals(String.class, paramType.getActualTypeArguments()[0]);
		assertEquals(Integer.class, paramType.getActualTypeArguments()[1]);
	}

	@Test
	public void testReturn_Subclass() throws Exception {
		Class<?> clazz = SubCalculator.class;
		Method method = clazz.getMethod("getId");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertEquals(String.class, result);
	}

	@Test
	public void testParam_Primitive() throws Exception {
		// double simpleSelectPrimitive(int param);
		Class<?> clazz = Level2Mapper.class;
		Method method = clazz.getMethod("simpleSelectPrimitive", int.class);
		Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
		assertEquals(1, result.length);
		assertEquals(int.class, result[0]);
	}

	@Test
	public void testParam_Simple() throws Exception {
		// void simpleSelectVoid(Integer param);
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("simpleSelectVoid", Integer.class);
		Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
		assertEquals(1, result.length);
		assertEquals(Integer.class, result[0]);
	}

	@Test
	public void testParam_Lv1Single() throws Exception {
		// N select(N param);
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("select", Object.class);
		Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
		assertEquals(1, result.length);
		assertEquals(String.class, result[0]);
	}

	@Test
	public void testParam_Lv2Single() throws Exception {
		// N select(N param);
		Class<?> clazz = Level2Mapper.class;
		Method method = clazz.getMethod("select", Object.class);
		Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
		assertEquals(1, result.length);
		assertEquals(String.class, result[0]);
	}

	@Test
	public void testParam_Lv2Multiple() throws Exception {
		// List<N> selectList(M param1, N param2);
		Class<?> clazz = Level2Mapper.class;
		Method method = clazz.getMethod("selectList", Object.class, Object.class);
		Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
		assertEquals(2, result.length);
		assertEquals(Integer.class, result[0]);
		assertEquals(String.class, result[1]);
	}

	@Test
	public void testParam_Lv2CustomClass() throws Exception {
		// Calculator<N> selectCalculator(Calculator<N> param);
		Class<?> clazz = Level2Mapper.class;
		Method method = clazz.getMethod("selectCalculator", Calculator.class);
		Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
		assertEquals(1, result.length);
		assertTrue(result[0] instanceof ParameterizedType);
		ParameterizedType paramType = (ParameterizedType) result[0];
		assertEquals(Calculator.class, paramType.getRawType());
		assertEquals(1, paramType.getActualTypeArguments().length);
		assertEquals(String.class, paramType.getActualTypeArguments()[0]);
	}

	@Test
	public void testParam_Lv1Array() throws Exception {
		// String[] simpleSelectArray();
		Class<?> clazz = Level1Mapper.class;
		Method method = clazz.getMethod("selectArray", List[].class);
		Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
		assertTrue(result[0] instanceof GenericArrayType);
		GenericArrayType genericArrayType = (GenericArrayType) result[0];
		assertTrue(genericArrayType.getGenericComponentType() instanceof ParameterizedType);
		ParameterizedType paramType = (ParameterizedType) genericArrayType.getGenericComponentType();
		assertEquals(List.class, paramType.getRawType());
		assertEquals(String.class, paramType.getActualTypeArguments()[0]);
	}

	@Test
	public void testParam_Subclass() throws Exception {
		Class<?> clazz = SubCalculator.class;
		Method method = clazz.getMethod("setId", Object.class);
		Type[] result = TypeParameterResolver.resolveParamTypes(method, clazz);
		assertEquals(String.class, result[0]);
	}

	@Test
	public void testReturn_Anonymous() throws Exception {
		Calculator<?> instance = new Calculator<Integer>();
		Class<?> clazz = instance.getClass();
		Method method = clazz.getMethod("getId");
		Type result = TypeParameterResolver.resolveReturnType(method, clazz);
		assertEquals(Object.class, result);
	}

	@Test
	public void testField_GenericField() throws Exception {
		Class<?> clazz = SubCalculator.class;
		Class<?> declaredClass = Calculator.class;
		Field field = declaredClass.getDeclaredField("fld");
		Type result = TypeParameterResolver.resolveFieldType(field, clazz);
		assertEquals(String.class, result);
	}

	@Test
	public void testReturnParam_WildcardWithUpperBounds() throws Exception {
		class Key {
		}
		@SuppressWarnings("unused")
		class KeyBean<S extends Key & Cloneable, T extends Key> {
			private S key1;
			private T key2;

			public S getKey1() {
				return key1;
			}

			public void setKey1(S key1) {
				this.key1 = key1;
			}

			public T getKey2() {
				return key2;
			}

			public void setKey2(T key2) {
				this.key2 = key2;
			}
		}
		Class<?> clazz = KeyBean.class;
		Method getter1 = clazz.getMethod("getKey1");
		assertEquals(Key.class, TypeParameterResolver.resolveReturnType(getter1, clazz));
		Method setter1 = clazz.getMethod("setKey1", Key.class);
		assertEquals(Key.class, TypeParameterResolver.resolveParamTypes(setter1, clazz)[0]);
		Method getter2 = clazz.getMethod("getKey2");
		assertEquals(Key.class, TypeParameterResolver.resolveReturnType(getter2, clazz));
		Method setter2 = clazz.getMethod("setKey2", Key.class);
		assertEquals(Key.class, TypeParameterResolver.resolveParamTypes(setter2, clazz)[0]);
	}
}

源码分析

主要是针对以上四种type类型的封装,三种类型获取方法入口都为同一个resolveType(returnType, srcType, declaringClass)

  • 获取字段的类型入口:resolveFieldType
  • 获取方法返回值类型入口:resolveReturnType
  • 获取方法入参类型 入口:resolveParamTypes
public class TypeParameterResolver {

	public static Type resolveReturnType(Method method, Type srcType) {
		// Generic: 带有泛型化参数
		Type returnType = method.getGenericReturnType();
		// 方法对应的类或者接口定义,[只能是public方法]
		Class<?> declaringClass = method.getDeclaringClass();
		// returnType: 方法返回类型
		// srcType: 使用class的对象
		// declaringClass:对应接口的对象
		return resolveType(returnType, srcType, declaringClass);
	}

	public static Type resolveFieldType(Field field, Type srcType) {
		Type fieldType = field.getGenericType();
		Class<?> declaringClass = field.getDeclaringClass();

		return resolveType(fieldType, srcType, declaringClass);
	}

	public static Type[] resolveParamTypes(Method method, Type srcType) {
		Type[] paramTypes = method.getGenericParameterTypes();
		Class<?> declaringClass = method.getDeclaringClass();
		Type[] result = new Type[paramTypes.length];
		for (int i = 0; i < paramTypes.length; i++) {
			result[i] = resolveType(paramTypes[i], srcType, declaringClass);
		}
		return result;
	}

	// type: 方法返回类型
	// srcType: 使用class的对象
	// declaringClass:对应接口的对象
	private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
		// 泛型方法 T test();中的T
		if (type instanceof TypeVariable) {
			return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
		}
		// 方法 List<String> test();
		else if (type instanceof ParameterizedType) {
			return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
		}
		// 方法 List<String>[] test();
		else if (type instanceof GenericArrayType) {
			return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
		}
		// 基本类型double,数组等String[][];
		else {
			return type;
		}
	}

	// List<String>[]
	private static Type resolveGenericArrayType(GenericArrayType genericArrayType, Type srcType,
			Class<?> declaringClass) {
		// List<String>[] -> List<String>
		Type componentType = genericArrayType.getGenericComponentType();
		Type resolvedComponentType = null;
		// N[]
		if (componentType instanceof TypeVariable) {
			resolvedComponentType = resolveTypeVar((TypeVariable<?>) componentType, srcType, declaringClass);
		}
		// N[][]
		else if (componentType instanceof GenericArrayType) {
			resolvedComponentType = resolveGenericArrayType((GenericArrayType) componentType, srcType, declaringClass);
		}
		// List<N>[]
		else if (componentType instanceof ParameterizedType) {
			resolvedComponentType = resolveParameterizedType((ParameterizedType) componentType, srcType,
					declaringClass);
		}
		if (resolvedComponentType instanceof Class) {
			return Array.newInstance((Class<?>) resolvedComponentType, 0).getClass();
		} else {
			return new GenericArrayTypeImpl(resolvedComponentType);
		}
	}

	// Map<String, String> -> parameterizedType -> getActualTypeArguments ->
	// [String, String]
	// Map<String, String> -> parameterizedType -> getRawType -> Map
	private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType,
			Class<?> declaringClass) {
		Class<?> rawType = (Class<?>) parameterizedType.getRawType();
		Type[] typeArgs = parameterizedType.getActualTypeArguments();
		Type[] args = new Type[typeArgs.length];
		for (int i = 0; i < typeArgs.length; i++) {
			// 方法 T test();中的T
			if (typeArgs[i] instanceof TypeVariable) {
				args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], srcType, declaringClass);
			}
			// 方法 List<String> test();
			else if (typeArgs[i] instanceof ParameterizedType) {
				args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], srcType, declaringClass);
			}

			// 泛型限定 List<? extends String> test(); --> upperBounds 上界
			// 泛型限定 List<? supper String> test(); --> lowerBounds 下界
			else if (typeArgs[i] instanceof WildcardType) {
				args[i] = resolveWildcardType((WildcardType) typeArgs[i], srcType, declaringClass);
			} else {
				args[i] = typeArgs[i];
			}
		}
		return new ParameterizedTypeImpl(rawType, null, args);
	}

	private static Type resolveWildcardType(WildcardType wildcardType, Type srcType, Class<?> declaringClass) {
		Type[] lowerBounds = resolveWildcardTypeBounds(wildcardType.getLowerBounds(), srcType, declaringClass);
		Type[] upperBounds = resolveWildcardTypeBounds(wildcardType.getUpperBounds(), srcType, declaringClass);
		return new WildcardTypeImpl(lowerBounds, upperBounds);
	}

	// 泛型限定 List<? extends String> test(); --> upperBounds 上界
	// 泛型限定 List<? supper String> test(); --> lowerBounds 下界
	private static Type[] resolveWildcardTypeBounds(Type[] bounds, Type srcType, Class<?> declaringClass) {
		Type[] result = new Type[bounds.length];
		for (int i = 0; i < bounds.length; i++) {
			if (bounds[i] instanceof TypeVariable) {
				result[i] = resolveTypeVar((TypeVariable<?>) bounds[i], srcType, declaringClass);
			} else if (bounds[i] instanceof ParameterizedType) {
				result[i] = resolveParameterizedType((ParameterizedType) bounds[i], srcType, declaringClass);
			} else if (bounds[i] instanceof WildcardType) {
				result[i] = resolveWildcardType((WildcardType) bounds[i], srcType, declaringClass);
			} else {
				result[i] = bounds[i];
			}
		}
		return result;
	}

	// typeVar:方法 T test();中的T
	// srcType: 使用class的对象
	// declaringClass:对应接口的对象
	private static Type resolveTypeVar(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass) {
		Type result = null;
		Class<?> clazz = null;
		if (srcType instanceof Class) {
			clazz = (Class<?>) srcType;
		} else if (srcType instanceof ParameterizedType) {
			ParameterizedType parameterizedType = (ParameterizedType) srcType;
			clazz = (Class<?>) parameterizedType.getRawType();
		} else {
			throw new IllegalArgumentException(
					"The 2nd arg must be Class or ParameterizedType, but was: " + srcType.getClass());
		}

		if (clazz == declaringClass) {
			Type[] bounds = typeVar.getBounds();
			if (bounds.length > 0) {
				return bounds[0];
			}
			return Object.class;
		}

		// 继承的父类class,保留泛型信息
		Type superclass = clazz.getGenericSuperclass();
		result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superclass);
		if (result != null) {
			return result;
		}

		// 继承的父类interfaces,保留泛型信息
		Type[] superInterfaces = clazz.getGenericInterfaces();
		for (Type superInterface : superInterfaces) {
			result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superInterface);
			if (result != null) {
				return result;
			}
		}
		return Object.class;
	}

	// typeVar: N
	// superclass: org.apache.ibatis.reflection.typeparam.Level0Mapper<E, F,
	// java.lang.String>
	// srcType:interface org.apache.ibatis.reflection.typeparam.Level1Mapper
	// declaringClass: interface org.apache.ibatis.reflection.typeparam.Level0Mapper
	// clazz:interface org.apache.ibatis.reflection.typeparam.Level1Mapper
	// superclass:org.apache.ibatis.reflection.typeparam.Level0Mapper<E, F,
	// java.lang.String>
	private static Type scanSuperTypes(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass, Class<?> clazz,
			Type superclass) {
		Type result = null;
		if (superclass instanceof ParameterizedType) {
			ParameterizedType parentAsType = (ParameterizedType) superclass;
			Class<?> parentAsClass = (Class<?>) parentAsType.getRawType();
			// 对应泛型参数对比:[L, M, N]->[E, F, class java.lang.String]
			// N -> class java.lang.String
			if (declaringClass == parentAsClass) {
				Type[] typeArgs = parentAsType.getActualTypeArguments();
				TypeVariable<?>[] declaredTypeVars = declaringClass.getTypeParameters();
				for (int i = 0; i < declaredTypeVars.length; i++) {
					if (declaredTypeVars[i] == typeVar) {
						if (typeArgs[i] instanceof TypeVariable) {
							TypeVariable<?>[] typeParams = clazz.getTypeParameters();
							for (int j = 0; j < typeParams.length; j++) {
								if (typeParams[j] == typeArgs[i]) {
									if (srcType instanceof ParameterizedType) {
										result = ((ParameterizedType) srcType).getActualTypeArguments()[j];
									}
									break;
								}
							}
						} else {
							result = typeArgs[i];
						}
					}
				}
			} else if (declaringClass.isAssignableFrom(parentAsClass)) {
				result = resolveTypeVar(typeVar, parentAsType, declaringClass);
			}
		} else if (superclass instanceof Class) {
			if (declaringClass.isAssignableFrom((Class<?>) superclass)) {
				result = resolveTypeVar(typeVar, superclass, declaringClass);
			}
		}
		return result;
	}

	private TypeParameterResolver() {
		super();
	}

	static class ParameterizedTypeImpl implements ParameterizedType {
		private Class<?> rawType;

		private Type ownerType;

		private Type[] actualTypeArguments;

		public ParameterizedTypeImpl(Class<?> rawType, Type ownerType, Type[] actualTypeArguments) {
			super();
			this.rawType = rawType;
			this.ownerType = ownerType;
			this.actualTypeArguments = actualTypeArguments;
		}

		@Override
		public Type[] getActualTypeArguments() {
			return actualTypeArguments;
		}

		@Override
		public Type getOwnerType() {
			return ownerType;
		}

		@Override
		public Type getRawType() {
			return rawType;
		}

		@Override
		public String toString() {
			return "ParameterizedTypeImpl [rawType=" + rawType + ", ownerType=" + ownerType + ", actualTypeArguments="
					+ Arrays.toString(actualTypeArguments) + "]";
		}
	}

	static class WildcardTypeImpl implements WildcardType {
		private Type[] lowerBounds;

		private Type[] upperBounds;

		private WildcardTypeImpl(Type[] lowerBounds, Type[] upperBounds) {
			super();
			this.lowerBounds = lowerBounds;
			this.upperBounds = upperBounds;
		}

		@Override
		public Type[] getLowerBounds() {
			return lowerBounds;
		}

		@Override
		public Type[] getUpperBounds() {
			return upperBounds;
		}
	}

	static class GenericArrayTypeImpl implements GenericArrayType {
		private Type genericComponentType;

		private GenericArrayTypeImpl(Type genericComponentType) {
			super();
			this.genericComponentType = genericComponentType;
		}

		@Override
		public Type getGenericComponentType() {
			return genericComponentType;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值