Mybatis框架基础支持层——反射工具箱之泛型解析工具TypeParameterResolver(4)
简介: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)的更多相关文章
- Mybatis框架基础支持层——反射工具箱之Reflector&ReflectorFactory(3)
说明:Reflector是Mybatis反射工具的基础,每个Reflector对应一个类,在Reflector中封装有该类的元信息, 以及基于类信息的一系列反射应用封装API public class ...
- Mybatis框架基础支持层——反射工具箱之实体属性Property工具集(6)
本篇主要介绍mybatis反射工具中用到的三个属性工具类:PropertyTokenizer.PropertyNamer.PropertyCopier. PropertyTokenizer: 主要用来 ...
- Mybatis框架基础支持层——反射工具箱之对象工厂ObjectFactory&DefaultObjectFactory(5)
ObjectFactory官方简介:MyBatis每次创建结果集对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成. 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认 ...
- Mybatis框架基础支持层——反射工具箱之MetaClass(7)
简介:MetaClass是Mybatis对类级别的元信息的封装和处理,通过与属性工具类的结合, 实现了对复杂表达式的解析,实现了获取指定描述信息的功能 public class MetaClass { ...
- Mybatis框架基础支持层——日志模块(8)
前言: java开发中常用的日志框架有Log4j,Log4j2,Apache Commons Log,java.util.logging,slf4j等,这些工具对外的接口不尽相同.为了统一这些工具的接 ...
- Mybatis框架基础支持层——解析器模块(2)
解析器模块,核心类XPathParser /** * 封装了用于xml解析的类XPath.Document和EntityResolver */ public class XPathParser { / ...
- MyBatis源码分析-基础支持层反射模块Reflector/ReflectorFactory
本文主要介绍MyBatis的反射模块是如何实现的. MyBatis 反射的核心类Reflector,下面我先说明它的构造函数和成员变量.具体方法下面详解. org.apache.ibatis.refl ...
- 精尽 MyBatis 源码分析 - 基础支持层
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- MyBatis 框架 基础应用
1.ORM的概念和优势 概念: 对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据 ...
随机推荐
- 怎么过滤
replace(str, " ", ""); 就是这么简单
- 微信报错 config:fail.Error:invalid signature
config:fail.Error:invalid signature 微信公众号报这个错,appid等各项都配置好,经过一番折腾,发现原来ip白明单设置了不是该服务器的ID,重新设置后就可以了
- ansible基础-playbooks
1. playbooks介绍 如果说ansible的modules是工具,inventory配置文件是原材料,那么playbook就是一封说明书,这里会记录任务是如何如何执行的,当然如果你愿意,这里也 ...
- [Swift]LeetCode289. 生命游戏 | Game of Life
According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellul ...
- [Swift]LeetCode623. 在二叉树中增加一行 | Add One Row to Tree
Given the root of a binary tree, then value v and depth d, you need to add a row of nodes with value ...
- [Swift]LeetCode725. 分隔链表 | Split Linked List in Parts
Given a (singly) linked list with head node root, write a function to split the linked list into k c ...
- java.lang.AbstractMethodError: org.mybatis.spring.transaction.SpringManagedTransaction.getTimeout()Ljava/lang/Integer; 报错解决
我的妈呀 真的是各种报错..... 这个问题 解决方法: https://www.cnblogs.com/beppezhang/p/6118661.html
- 如何解决http请求返回结果中文乱码
如何解决http请求返回结果中文乱码 1.问题描述 http请求中,请求的结果集中包含中文,最终以乱码展示. 2.问题的本质 乱码的本质是服务端返回的字符集编码与客户端的编码方式不一致. 场景的如服务 ...
- eclipse neon 发布
2016年6月28日,Eclipse基金会宣布发布Eclipse Neon,这个版本的IDE支持Java.JavaScript.C/C++.PHP和Fortran等多种编程语言.这一次的发布集成了77 ...
- SpringCloud(9)---mysql实现配置中心
mysql实现配置中心 本公司配置数据的管理是通过mysql进行配置管理,因为已经搭建好了,所以自己动手重新搭建一遍,熟悉整个流程.有关项目源码后期会补上github地址 微服务要实现集中管理微服务配 ...