简介TypeParameterResolver是一个工具类,提供一系列的静态方法,去解析类中的字段、方法返回值、方法参数的类型。

在正式介绍TypeParameterResolver之前,先介绍一个JDK提供的接口Type,因为TypeParameterResolver的实现会涉及到它的实现;它是所有类型的父接口,在JDK实现中,Type接口拥有四个接口和一个实现类分别代表不同的数据类型;

分别是:

  • 类Class:表示原始类型。Class对象表示JVM的一个类和接口,每个java类在JVM里都是一个Class对象,在程序中可以通过"类名.class","对象.getClass","Class.forName()"获取到,数组也被映射为Class对象,所有元素类型相同且维数相同的数组共享同一个Class对象;
  • 接口ParameterizedType:表示的是参数化类型,例如:List<String>、Map<Integer,String>这种带范型的类型;
  • 接口TypeVariable:表示的类型变量,用来反映在JVM编译泛型前的信息,例如:List<T>中的T就是类型变量,在编译时需被转换成一个具体的类型后才能被使用。
  • 接口GenericArrayType:表示的是数组类型且组成元素是ParameterizedType或TypeVariable。例如:List<String>[]或T[]
  • 接口WildcardType:表示的是通配符类型,;例如 ? extends Number 和 ? super Integer 。

Type的实现和子接口源码就不贴出来了,下面会介绍一下上述四个接口的主要方法

  • 接口ParameterizedType:

    • Type  getRawType( )——返回参数化类型的最外层类型,例如List<String> => List;
    • Type[ ]  getActualTypeArguments( )——获取参数化类型的类型变量或者实际类型列表,例如Map<Integer,String>的实际类型列表Integer和String。需要注意的是该列表的元素也是Type接口,可能存在多层嵌套的情况;
    • Type  getOwnerType( )——返回的是类型所属的类型,例如存在A<T>类,其中定义了内部类InnerA<I>,则InnerA<I>的所属类型为A<T>,如果是顶层类型,则返回null;
  • 接口TypeVariable:
    • Type[ ]  getBounds( )——获取类型变量的上边界,如未明确声明上边界则默认为Object,例如:class Test<K extends Person>中K的上边界就是Person;
    • D  getGenericDecralation( )——获取声明该类型变量的原始类型,例如class Test<K extends Person>中的原始类型就是Test;
    • String  getName( )——获取在源码中定义是的名字,上例为K;
  • 接口GenericArrayType:Type  getGenericComponentType( )——返回数组的元素类型
  • 接口WildcardType:
    • Type[ ]  getUpperBounds( )——返回泛型变量的上界;
    • Type[ ]  getLowerBounds( )——返回泛型变量的下界;
       

下面正式介绍本篇主角TypeParameterResolver工具类:

如上图:

工具类主要有三个对外开放的方法,分别是

resolveFieldType(解析字段的类型),resolveReturnType(解析方法返回类型)和resolveParamTypes(解析方法入参的类型)。

三个方法获取到需要解析的类型后,调用resolveType方法进行统一的处理。

resolveType方法根据入参的类型的类别,分别调用resolveTypeVar(类型变量解析),resolveParameterizedType(参数化类型解析)和resolveGenericArrayType(泛型数组)解析。

public class TypeParameterResolver {

    /**
* srcType:被反射时调用的类型,即被解析的方法或字段是通过那个类型反射出来的
*
* declaringClass:定义被解析的方法或字段的class类型,即这个方法/字段是定义在那个class中的
*
* example:
*
* <p>
* public interface A<N>{
* public N getVal();
* }
*
* public interface B extends A<String>{}
* </p>
* 如上面代码所示,如果通过B接口获取到的getVal方法并对其返回值进行解析,则srcType表示B的类型,declaringClass表示A的类型
*/
public static Type resolveFieldType(Field field, Type srcType) {
// 获取字段的声明类型
Type fieldType = field.getGenericType(); // 获取字段定义所在的类的Class对象
Class<?> declaringClass = field.getDeclaringClass(); // 调用 resolveType方法进行后续处理
return resolveType(fieldType, srcType, declaringClass);
} public static Type resolveReturnType(Method method, Type srcType) {
//获取方法的返回类型
Type returnType = method.getGenericReturnType(); //获取方法定义的类的类型
Class<?> declaringClass = method.getDeclaringClass(); // 调用 resolveType方法进行后续处理
return resolveType(returnType, 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++) {
// 调用 resolveType方法进行后续处理
result[i] = resolveType(paramTypes[i], srcType, declaringClass);
}
return result;
} private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
if (type instanceof TypeVariable) {
//解析TypeVariable类型
return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
} else if (type instanceof ParameterizedType) {
//解析ParameterizedType类型
return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
} else if (type instanceof GenericArrayType) {
//解析GenericArrayType类型
return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
} else {
//如果为普通的Class类型就直接返回
return type;
}
} private static Type resolveGenericArrayType(GenericArrayType genericArrayType, Type srcType, Class<?> declaringClass) {
//去掉一层[]后的泛型类型变量
Type componentType = genericArrayType.getGenericComponentType();
Type resolvedComponentType = null; //根据去掉一维数组后的类型变量,再根据其类型递归解析
if (componentType instanceof TypeVariable) { //如果去掉后为TypeVariable类型,则调用resolveTypeVar方法
resolvedComponentType = resolveTypeVar((TypeVariable<?>) componentType, srcType, declaringClass);
} else if (componentType instanceof GenericArrayType) { //如果去掉仍为GenericArrayType类型,则递归调用resolveGenericArrayType方法
resolvedComponentType = resolveGenericArrayType((GenericArrayType) componentType, srcType, declaringClass);
} else if (componentType instanceof ParameterizedType) { //如果去掉后为ParameterizedType类型,则调用resolveParameterizedType方法处理
resolvedComponentType = resolveParameterizedType((ParameterizedType) componentType, srcType, declaringClass);
}
if (resolvedComponentType instanceof Class) { //如果处理后的结果为基本的Class类型,则返回对应的Class的数组类型(处理N[][])。
return Array.newInstance((Class<?>) resolvedComponentType, 0).getClass();
} else { //否则包装为自定义的GenericArrayTypeImpl类型
return new GenericArrayTypeImpl(resolvedComponentType);
}
} 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++) {
if (typeArgs[i] instanceof TypeVariable) {
//解析TypeVariable类型
args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], srcType, declaringClass);
} else if (typeArgs[i] instanceof ParameterizedType) {
//解析ParameterizedType类型
args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], srcType, declaringClass);
} else if (typeArgs[i] instanceof WildcardType) {
//是解析WildcardType类型(其类型实参是通配符表达式)
args[i] = resolveWildcardType((WildcardType) typeArgs[i], srcType, declaringClass);
} else {
//普通Class类型,直接返回
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); //包装成自定义的WildcardTypeImpl类型返回
return new WildcardTypeImpl(lowerBounds, upperBounds);
} 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;
} /**
* 解析具体的类型变量指代的类型。
* 1.如果srcType的Class类型和declaringClass为同一个类,表示获取该类型变量时被反射的类型就是其定义的类型,
* 则取该类型变量定义是有没有上限,如果有则使用其上限代表其类型,否则就用Object。
*
* 2.如果不是,则代表declaringClass是srcType的父类或者实现的接口,则解析继承中有没有定义其代表的类型
*/
private static Type resolveTypeVar(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass) {
Type result = null;
Class<?> clazz = null;
/**
* 判断srcType是否为Class/ParameterizedType类型
* 如果不是这两种类型这抛出异常
*/
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());
} /**
* 如果declaringClass和srcType的实际类型相等则表示无法获取其类型实参。
* 如果typeVar有上限限定则返回其上限,否则返回Object处理
*/
if (clazz == declaringClass) {
Type[] bounds = typeVar.getBounds();
if (bounds.length > 0) {
return bounds[0];
}
return Object.class;
} Type superclass = clazz.getGenericSuperclass();
result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superclass);
if (result != null) {
return result;
} /**
* 如果父类的定义中没有,则处理其实现的接口。
*/
Type[] superInterfaces = clazz.getGenericInterfaces();
for (Type superInterface : superInterfaces) {
result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superInterface);
if (result != null) {
return result;
}
}
//如果父类或者实现的接口中都没有获取到形参对应的实参,则返回Object.class
return Object.class;
} /**
* 通过对父类/接口的扫描获取其typeVar指代的实际类型
*/
private static Type scanSuperTypes(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass, Class<?> clazz, Type superclass) {
Type result = null;
/**
* 判断处理的父类superclass是否为参数化类型,如果不是则代表declaringClass和superclass的基本Class
* 类型不是同一个类。
*/
if (superclass instanceof ParameterizedType) {
//如果为ParameterizedType,则获取它基本类型
ParameterizedType parentAsType = (ParameterizedType) superclass;
Class<?> parentAsClass = (Class<?>) parentAsType.getRawType(); if (declaringClass == parentAsClass) {
//如果declaringClass和parentAsClass表示同一类型,则通过typeVar在declaringClass的泛型形参的index获取其在supperClass中定义的类型实参
Type[] typeArgs = parentAsType.getActualTypeArguments();
TypeVariable<?>[] declaredTypeVars = declaringClass.getTypeParameters(); for (int i = 0; i < declaredTypeVars.length; i++) {
//循环判断当前处理的类型是否属于所属的类型描述符中的变量
if (declaredTypeVars[i] == typeVar) {
/**
* 如果supperClass中定义的类型形参还是类型变量则取srcType中的类型形参的定义
* 如果srcType中的类型形参还是类型变量则不处理。
*/
if (typeArgs[i] instanceof TypeVariable) {
//其子类中的所有泛型描述符
TypeVariable<?>[] typeParams = clazz.getTypeParameters();
for (int j = 0; j < typeParams.length; j++) {
if (typeParams[j] == typeArgs[i]) {
//判断是否为ParameterizedType,则去实际代表的类型
if (srcType instanceof ParameterizedType) {
result = ((ParameterizedType) srcType).getActualTypeArguments()[j];
}
break;
}
}
} else {
//如果不是TypeVariable,直接取对应的类型
result = typeArgs[i];
}
}
}
} else if (declaringClass.isAssignableFrom(parentAsClass)) {
//通过判断superclass是否是declaringClass的子类(由于java类可以实现多个接口),进行递归解析
result = resolveTypeVar(typeVar, parentAsType, declaringClass);
}
} else if (superclass instanceof Class) {
//如果superclass为Class类型,通过判断superclass是否是declaringClass的子类(由于java类可以实现多个接口),进行递归解析
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;
}
}
}

Mybatis框架基础支持层——反射工具箱之泛型解析工具TypeParameterResolver(4)的更多相关文章

  1. Mybatis框架基础支持层——反射工具箱之Reflector&ReflectorFactory(3)

    说明:Reflector是Mybatis反射工具的基础,每个Reflector对应一个类,在Reflector中封装有该类的元信息, 以及基于类信息的一系列反射应用封装API public class ...

  2. Mybatis框架基础支持层——反射工具箱之实体属性Property工具集(6)

    本篇主要介绍mybatis反射工具中用到的三个属性工具类:PropertyTokenizer.PropertyNamer.PropertyCopier. PropertyTokenizer: 主要用来 ...

  3. Mybatis框架基础支持层——反射工具箱之对象工厂ObjectFactory&DefaultObjectFactory(5)

    ObjectFactory官方简介:MyBatis每次创建结果集对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成. 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认 ...

  4. Mybatis框架基础支持层——反射工具箱之MetaClass(7)

    简介:MetaClass是Mybatis对类级别的元信息的封装和处理,通过与属性工具类的结合, 实现了对复杂表达式的解析,实现了获取指定描述信息的功能 public class MetaClass { ...

  5. Mybatis框架基础支持层——日志模块(8)

    前言: java开发中常用的日志框架有Log4j,Log4j2,Apache Commons Log,java.util.logging,slf4j等,这些工具对外的接口不尽相同.为了统一这些工具的接 ...

  6. Mybatis框架基础支持层——解析器模块(2)

    解析器模块,核心类XPathParser /** * 封装了用于xml解析的类XPath.Document和EntityResolver */ public class XPathParser { / ...

  7. MyBatis源码分析-基础支持层反射模块Reflector/ReflectorFactory

    本文主要介绍MyBatis的反射模块是如何实现的. MyBatis 反射的核心类Reflector,下面我先说明它的构造函数和成员变量.具体方法下面详解. org.apache.ibatis.refl ...

  8. 精尽 MyBatis 源码分析 - 基础支持层

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  9. MyBatis 框架 基础应用

    1.ORM的概念和优势 概念: 对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据 ...

随机推荐

  1. SPARK-AM-TrackURL-UI-500

    HTTP ERROR 500 Problem accessing /proxy/application_1538120222810_0072/. Reason: Connection refused ...

  2. 编译的时候出现 usr/bin/ld: cannot find -lxxx 的错误

    比如错误为: usr/bin/ld: cannot find -labc 首先要明白的是 labc 代表的是 libabc.so 明白了这个之后,我们就知道了问题是:在编译的过程中,需要 libabc ...

  3. SSIS - 4.使用表达式任务和脚本任务实现更改变量和输出变量值

    一.脚本任务 脚本任务是SSIS包中功能很强大的组件,尤其当内置的任务无法实现我们需要的功能的时候,我们都可以使用脚本任务来实现.脚本任务使用VSTA(Microsoft Visual Studio ...

  4. APP研发录笔记

    一.消灭全局变量 在内存不足时,系统会回收一部分闲置的资源,由于App被切换到后台,所以之前存放的全局变量很容易被回收,这时再切换到前台继续使用,会报空指针崩溃.想彻底解决这个问题,就要使用序列化. ...

  5. [SQL]LeetCode262.行程和用户 | Trips and Users

    SQL架构 Create table If Not Exists Trips (Id )) Create table If Not Exists Users (Users_Id ), Role ENU ...

  6. Mysql数据库和表的增删改查以及数据备份&恢复

    数据库 查看所有数据库 show databases; 使用数据库 use 数据库名; 查看当前使用的数据库 select database(); 创建数据库 create database 数据库名 ...

  7. Oracle synonym 同义词

    Oracle synonym 同义词 1.Oracle synonym 同义词是数据库当前用户通过给另外一个用户的对象创建一个别名,然后可以通过对别名进行查询和操作,等价于直接操作该数据库对象. 2. ...

  8. 利用Python爬去囧网福利(多线程、urllib、request)

    import os; import urllib.request; import re; import threading;# 多线程 from urllib.error import URLErro ...

  9. C# Serialize

    一.序列化又称为串行化,是.NET运行时环境用来支持用户自定义类型的机制,目的是以某种存储给对象持久化,或者是将这种对象传输到另一个地方, 二. .NET框架提供了两种序列化的方式 一种是使用Bina ...

  10. pdf生成库-libharu编译

    相关文章:libharu 源码编译 VS2010 1.首先下载libharu源码,libharu依赖于libpng和libzib,如果编译过libpng和libzib的话,直接拿过来用即可.否则需要自 ...