美文网首页MyBatis源码剖析
[MyBatis源码分析 - 反射器模块 - 组件四] Type

[MyBatis源码分析 - 反射器模块 - 组件四] Type

作者: 小胡_鸭 | 来源:发表于2020-10-22 23:43 被阅读0次

    一、简介

      TypeParameterResolver 是一个类型参数解析器,即JavaBean中可能带泛型如 List<T>、通配符如 <? super SubClass>,而且可能复杂的继承关系,为了获取到运行时正确具体的类型(包括属性类型、方法参数类型、方法返回值类型),需要使用本类解析类型参数,对外暴露的解析属性、方法参数类型、方法返回值类型对应的方法分别为 #resolveFieldType()#resolveParamTypes()#resolveReturnType()

    二、Type 的基础背景知识

      Type 翻译成中文是类型,Class 是类,平时我们接触比较多的是 Class,那这两者有什么关系?其实 Type 是一个接口,Class 是它的实现类!那 Type 还有其他继承的子接口或实现类吗?答案是有,并且各种类型对应不同形式的泛型比如 T、Set<T>、T[]、<? super Xxx>,Type 跟泛型息息相关,它有四个子接口和一个实现类,类图如下:

    • 1、Class:比较常见,表示一个原始类型,每个类或接口都有对应的 Class 对象,数组也有对应的 Class 对象,所有元素类型相同且维度相同的数组都共享同一个 Class 对象。
    • 2、ParameterizedType参数化类型,形如 Set<String>、Map<String, Object> 这种带泛型的类型都是参数化类型。ParameterizedType 是一个接口,定义了三个方法,分别为:
      • Type[] getActualTypeArguments():获取参数化类型的类型变量或是实际类型列表。比如 Map<String, Object> 的实际泛型列表为 [String, Object],当然实际使用中还存在嵌套的情况,比如 Map<String, List<User>>,这时要解析到 value 中嵌套的具体类型,还得对 List<User> 再做解析,所以 TypeParameterResolver 中的实现带有递归调用。
      • Type getRawType():获取参数话类型中的原始类型。比如 Map<String, Object> 的原始类型为 Map。
      • Type getOwnerType():返回类型所属的类型。一般的类是在一个单独的类文件中定义的,可视为顶层类型,不为其他类型所有,所以返回 null;如果类型是一个内部类,则返回类型为定义该类的类型,如 Map.Entry<K, V> 是在 Map<K, V> 中定义的,所以其所属的类型为 Map<K, V>

      代码演示:

    public class ParameterizedTypeTest {
    
        Map<String, Integer> map = new HashMap<String, Integer>();
        
        public static void test(Type type) {
            if (type instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                Type[] typeArgs = parameterizedType.getActualTypeArguments();
                for (Type typeArg : typeArgs) {
                    System.out.println(typeArg);
                }
                System.out.println("RawType: " + parameterizedType.getRawType());
                System.out.println("OwnerType: " + parameterizedType.getOwnerType());
            } else {
                System.out.println("type is not ParameterizedType");
            }
        }   
        
        public static void main(String[] args) throws NoSuchFieldException, SecurityException {
            ParameterizedTypeTest obj = new ParameterizedTypeTest();
            Type type = obj.getClass().getDeclaredField("map").getGenericType();
            test(type);
        }
        
    }
    

      执行结果:

    class java.lang.String
    class java.lang.Integer
    RawType: interface java.util.Map
    OwnerType: null
    
    • 3、GenericArrayType通用数组类型,形如 List<String>[]、T[] 这种数组类型都是通用数组类型,接口中值定义了 #getGenericComponentType() 方法来获取数组元素类型。

      代码演示:

    public class GenericArrayTypeTest {
        List<String> listArray[] = new ArrayList[10];   
        
        public static void main(String[] args) throws NoSuchFieldException, SecurityException {
            GenericArrayTypeTest obj = new GenericArrayTypeTest();
            Type type = obj.getClass().getDeclaredField("listArray").getGenericType();
            if (type instanceof GenericArrayType) {
                GenericArrayType genericArrayType = (GenericArrayType) type;
                Type componentType = genericArrayType.getGenericComponentType();
                System.out.println(componentType);
            } else {
                System.out.println("type is not GenericArrayType");
            }
        }
    }
    

      执行结果:

    java.util.List<java.lang.String>
    
    • 4、TypeVariable类型变量,用来反映在JVM编译该泛型前的信息,形如 Set<T> 中的 T 就是类型变量,在编译时需要被转换为一个具体的类型后才能正常使用。TypeVariable 同样也是一个接口,接口中定义了三个方法,分别为:
      • Type[] getBounds():获取类型变量的上边界,如 List<T extends User> 中 T 的上边界就是 User,如果没有明确指定上边界,则为 Object。
      • D getGenericDeclaration():返回声明该类型变量的原始类型,比如上面的 T 其原始类型为 List。
      • String getName():返回类型变量定义时的名字,比如 T。

      代码演示:

    public class TypeVariableTest<T> {
    
        T arr; 
        
        public static void main(String[] args) throws NoSuchFieldException, SecurityException {
            TypeVariableTest obj = new TypeVariableTest<String>();
            Type type = obj.getClass().getDeclaredField("arr").getGenericType();
            if (type instanceof TypeVariable) {
                TypeVariable typeVariable = (TypeVariable) type;
                for (Type t : typeVariable.getBounds()) {
                    System.out.println(t);
                }           
                System.out.println(typeVariable.getGenericDeclaration());
                System.out.println(typeVariable.getName());     
            } else {
                System.out.println("type is not TypeVariable");
            }
        }
    }
    

      执行结果:

    class java.lang.Object
    class com.mybatis.study.TypeVariableTest
    T
    
    • 5、WildcardType:通配符泛型,通配符泛型跟普通泛型相比,区别在于不仅可以指定类型变量的上边界如 ? extends Number,还可以指定下边界 ? super Integer,除此之外,普通泛型使用时必须指定具体类型,而通配符泛型不需要,适用于具体类型不确定的情况,通常用于带泛型方法的传参。WildcardType 接口有两个方法,分别为:
      • Type[] getUpperBounds():获取泛型变量的上界。
      • Type[] getLowerBounds():获取泛型变量的下界。

      代码演示:

    public class WildcardTypeTest { 
        Map<? super Long, ? extends Number> map = new HashMap<>(); 
        
        public static void test(Type type) {
            if (type instanceof WildcardType) {
                WildcardType wildcardType = (WildcardType) type;
                Type[] uppperTypes = wildcardType.getUpperBounds();
                Type[] lowerTypes = wildcardType.getLowerBounds();
                System.out.println("UpperType is:");
                for (Type t : uppperTypes) {
                    System.out.println(t);
                }
                System.out.println("LowerType is:");
                for (Type t : lowerTypes) {
                    System.out.println(t);
                }
            } else {
                System.out.println("type is not WildcardType");
            }
        }
        
        public static void main(String[] args) throws NoSuchFieldException, SecurityException {     
            WildcardTypeTest obj = new WildcardTypeTest();
            Type type = obj.getClass().getDeclaredField("map").getGenericType();
            System.out.println(type);
            if (type instanceof ParameterizedType) {            
                Type[] actTypes = ((ParameterizedType) type).getActualTypeArguments();
                for (Type t : actTypes) { 
                    test(t);
                    System.out.println();
                }
            }       
        }
    }
    

      执行结果:

    java.util.Map<? super java.lang.Long, ? extends java.lang.Number>
    UpperType is:
    class java.lang.Object
    LowerType is:
    class java.lang.Long
    
    UpperType is:
    class java.lang.Number
    LowerType is:
    

    三、调用关系

      TypeParameterResolver 中的方法都是静态方法,三个对外暴露的方法为:

    • (1)#Type resolveFieldType(Field field, Type srcType):解析属性类型。
    • (2)#Type resolveReturnType(Method method, Type srcType):解析方法返回值类型。
    • (3)#Type[] resolveParamTypes(Method method, Type srcType):解析方法参数类型,由于一个方法可能有多个参数,所以返回的是一个数组。

       这几个方法都会调用 Type resolveType(Type type, Type srcType, Class<?> declaringClass),该方法根据传入的 type 参数的具体类型,再去调用其他方法,调用关系如图:

    四、方法功能

    1、Type resolveFieldType(Field field, Type srcType)
    2、Type resolveReturnType(Method method, Type srcType)
    3、Type[] resolveParamTypes(Method method, Type srcType)

    【功能】解析属性、返回值、方法参数类型。
    【源码与注释】

      /**
       * 解析属性类型
       */
      public static Type resolveFieldType(Field field, Type srcType) {
        // 属性类型
        Type fieldType = field.getGenericType();                    // Map<K, V>
        // 定义的类
        Class<?> declaringClass = field.getDeclaringClass();        // A
        // 调用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++) {
          result[i] = resolveType(paramTypes[i], srcType, declaringClass);
        }
        return result;
      }
    

    【解析】在上述的方法中,传入的 methodfield 参数可能带泛型,而拥有(声明或继承或实现)属性和方法被使用的类 srcType 参数可能带具体类型,所以要解析具体类型,要找到哪个泛型对应哪个具体类型。

    4、Type resolveType(Type type, Type srcType, Class<?> declaringClass)

    【功能】被公有方法调用的方法,针对不同类型调用不同的方法去解析具体的类型信息,起到承上启下的作用。
    【源码与注解】

      private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
        // (1) 如果是类型变量,如:T
        if (type instanceof TypeVariable) {
          return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
        // (2) 如果是参数类型,如:Map<K, V>
        //     如果是通配符泛型,如:Map<K extends Xxx, V super Yyy>,
        //     因为其肯定是嵌套在参数类型中的,所以不用去判断泛型类型是否通配符泛型
        } else if (type instanceof ParameterizedType) {
          return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
        // (3) 如果是泛型数组类型:如:T[]、Map<K, V>[]
        } else if (type instanceof GenericArrayType) {
          return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
        } else {
        // (4) 除掉上面四种可能,剩下的只能是Class类型,直接返回
          return type;
        }
      }
    

    5、Type resolveTypeVar(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass)

    【功能】解析类型变量的具体类型。
    【源码和注解】

      private static Type resolveTypeVar(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass) {
        Type result = null;               // 保存解析类型变量类型结果的局部变量
        Class<?> clazz = null;            // 保存使用类型的原始类型的局部变量
        // (1) 使用的类中继承了带泛型的父类并在类定义中直接指定泛型类型的情况
        if (srcType instanceof Class) {
          clazz = (Class<?>) srcType;
        // (2) 使用的类中继承了带泛型的父类并在类定义中继续对外暴露泛型的情况
        } 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());
        }
    
        // (3) 类中带泛型,既没指定具体类型又没对外暴露,默认泛型类型为 Object
        if (clazz == declaringClass) {
          return Object.class;
        }
    
        // (4) 获取使用类定义时形式的带泛型的父类
        Type superclass = clazz.getGenericSuperclass();
        // (5) 解析类型变量的具体类型
        result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superclass);
        if (result != null) {
          return result;
        }
        // (6) 类还可能实现了带泛型的接口,如果类型变量无法通过父类解析,可能要依赖泛型接口解析
        Type[] superInterfaces = clazz.getGenericInterfaces();
        for (Type superInterface : superInterfaces) {
          result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superInterface);
          if (result != null) {
            return result;
          }
        }
        //(7)解析不到具体类型,认定类型变量可以用作任意类型,即Object
        return Object.class;
      }
    

    【解析】
      首先明确一下 declaringClass 是带类型变量的属性或方法直接声明的类,srcType 是拥有这些属性方法被直接使用的类,二者是有区别的,eg:

        static class B<T> {
            T t;
        }
    
        static class SubClassB extends B<String> {}
    

      类 SubClassB 通过继承类 B,拥有了属性 t,但对属性 t 来说,声明它的类是 B,在这个例子中,srcType 是 SubClassB,declaringClass 是 B。

    (1)若使用的类继承了带泛型的父类并在类定义中直接指定泛型类型的情况,则 srcType 的具体类型就是 Class,如上面的例子。
    (2)若使用的类中继承了带泛型的父类并在类定义中继续对外暴露泛型的情况,如:

    static class SubClassB2<T> extends B<T> {}
    

    则 srcType 为 SubClassB<T>,类型为 ParameterizedType,所以获取原始类型要通过 ParameterizedType.getRawType() 获取。
      如果 srcType 不是上面这两种情况,则是不合理的,直接抛出异常。
    (3)类中带泛型,既没指定具体类型又没对外暴露,默认泛型类型为 Object,如:

    static class SubClassB3 extends B<T> {}
    

    (4)获取使用类定义时形式的带泛型的父类,通过 getGenericSuperclass() 得到的通常是个 ParameterizedType ,如:

    static class SubClassB4 extends B<C> {}
    

    SubClassB3SubClassB4 获得的 super 是不一样的,分别是 B<T>、B<C>。
    (5)解析类型变量的具体类型,调用 #scanSuperTypes(),其源码下面结合例子说明。
    (6)类还可能实现了带泛型的接口,如果类型变量无法通过父类解析,可能要依赖泛型接口解析,如:

        static interface CI<T> {
            T getProp();
            void setProp(T prop);
        }
        static class SubClassC implements CI<String> {
            String prop;
    
            @Override
            public String getProp() {
                return prop;
            }
    
            @Override
            public void setProp(String prop) {
                this.prop = prop;
            }
        }
    

    (7)解析不到具体类型,认定类型变量可以用作任意类型,即Object,将上面的例子改改,如下:

        static class SubClassC2<T> implements CI<T> {
            T prop;
    
            @Override
            public T getProp() {
                return prop;
            }
    
            @Override
            public void setProp(T prop) {
                this.prop = prop;
            }
        }
    

    【实例演示】

    (1)类定义

        static class B<T> {
            T t;
        }
    
        static class SubClassB extends B<String> {}
    

    (2)测试代码

        @Test
        public void testSubClassB() throws NoSuchFieldException {
            Field f = B.class.getDeclaredField("t");
            Type type = TypeParameterResolver.resolveFieldType(f, SubClassB.class);
        }
    

    【思路分析 -- 主要描述 #scanSuperTypes() 的处理步骤】

    • (2.1)泛型的来源:属性为 B.t,类型为 T,类型为 TypeVariable,B 中的类型变量的数组为 { T }
    • (2.2)具体类型的来源:SubClass 类定义中直接指定了继承的父类泛型,所以其泛型父类为 B<String>,泛型类型数组为 {String}
    • (2.3)关联:沿着 SubClass 的继承链追溯,父类为 B,判断到跟声明属性 t 的类一致,所以 {String} 的元素跟 {T} 一一对应,所以 T 的具体类型是 String

    (3)对测试代码的第二个打个断点,执行跟踪


      在入口方法中,可以看到几个传递给后面方法的参数的值,进入中转方法

      很明显,属性 t 的类型是类型变量,所以交给 #resolveTypeVar 处理

      SubClassB 的类型是 Class,直接类型转换

      对于 SubClassB 来说,拥有的属性 t 定义的类是 B,条件不成立,所以继续解析

      解析到 SubClassB 的带泛型父类为 B<java.lang.String>,调用 #scanSuperType() 接着进行下一步处理,处理流程如下:


    6、ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType, Class<?> declaringClass)

    【功能】解析参数化类型的具体类型。
    【源码与注解】

      private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType, Class<?> declaringClass) {
        // (1) 获取参数化类型的原始类型
        Class<?> rawType = (Class<?>) parameterizedType.getRawType();
        // (2) 获取参数化类型的参数类型组成的数组
        Type[] typeArgs = parameterizedType.getActualTypeArguments();
        Type[] args = new Type[typeArgs.length];
        // (3) 遍历每个类型,解析其具体类型
        for (int i = 0; i < typeArgs.length; i++) {
          // (3.1) 参数类型可能是类型变量
          if (typeArgs[i] instanceof TypeVariable) {
            args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], srcType, declaringClass);
          // (3.2) 参数类型可能是嵌套的参数化类型
          } else if (typeArgs[i] instanceof ParameterizedType) {
            args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], srcType, declaringClass);
          // (3.3) 参数化类型可能是通配符泛型
          } else if (typeArgs[i] instanceof WildcardType) {
            args[i] = resolveWildcardType((WildcardType) typeArgs[i], srcType, declaringClass);
          // (3.4) 可能直接是一个Class类型
          } else {
            args[i] = typeArgs[i];
          }
        }
        // (4) 封装成内部类ParameterizedTypeImpl对象返回
        return new ParameterizedTypeImpl(rawType, null, args);
      }
    

    【解析】
    (1)获取参数化类型的原始类型,如 List<String> 的原始类型为 List
    (2)获取参数化类型的所有参数类型组成的类型数组,如 Map<K, V> 的参数类型数组为 { K, V }
    (3)遍历参数类型数组中的元素,解析其具体类型。

    • (3.1)参数类型可能是类型变量,如 K
    • (3.2)参数类型可能是嵌套的参数化类型,如 List<Map<K, V>>,参数类型为 Map<K, V>
    • (3.3)参数化类型可能是通配符泛型,如 Set<? extends Xxx>,参数类型为 ? extends Xxx
    • (3.4)最常见的参数化类型是一个具体类型,即Class,如 List<String>,参数类型为 String

    (4)封装成内部类ParameterizedTypeImpl对象返回,实现代码很简单,后面再介绍。

    【实例演示】

    (1)测试类定义

        static class A<K, V> {
            Map<K, V> map;
        }
    
        static class SubClassA<T> extends A<T, T> {}
    
        static class TestType {
            SubClassA<Long> sa = new SubClassA<Long>();
        }
    

    (2)测试代码

        @Test
        public void testSubClassA2() throws NoSuchFieldException {
            Type saType = TestType.class.getDeclaredField("sa").getGenericType();
            printTypeInfo(saType);
            Field f = A.class.getDeclaredField("map");
            Type type = TypeParameterResolver.resolveFieldType(f, saType);
            printTypeInfo(type);
        }
    

    【解析分析】

    • (2.1)泛型的来源:属性 A.map,类型为 Map<K, V>,A中的类型变量数组为 { K, V }
    • (2.2)具体类型的来源:TestType 类在定义属性 sa 时,指定了 SubClassA 中的类型为 Long,所以其泛型父类为 A<Long, Long>,泛型类型数组具体类型为 { Long, Long }
    • (2.3)关联:沿着 SubClassA 的继承链追溯,父类为 A,判断到跟声明属性 map 的类 A 一致,所以具体类型数组 { Long, Long } 跟泛型类型数组 { K, V } 一一对应。

    (3)断点跟踪


      属性类型为 Map<K, V>,声明类为 A

      type 为 Map<K, V>,这是个参数化类型,所以走了第二个分支,调用 #resolveParameterizedType() 方法处理

       Map<K, V> 中的每个参数类型都是类型变量,调用 #resolveTypeVar 处理

      SubClassA<Long> 是一个参数化类型,其原始类型为 SubClassA,原始类型定义的泛型父类为 A<T, T>,解析具体类型的步骤如下所示,最终解析出 K 的类型为 Long,V的类型也为Long


    7、Type resolveWildcardType(WildcardType wildcardType, Type srcType, Class<?> declaringClass)

    【功能】解析通配符泛型的上下界限,并解析每个界限的具体类型。
    【源码与注解】

      private static Type resolveWildcardType(WildcardType wildcardType, Type srcType, Class<?> declaringClass) {
        // (1) 获取通配符泛型的下界数组,如 ? super Long,获得数组为 { Long }
        Type[] lowerBounds = resolveWildcardTypeBounds(wildcardType.getLowerBounds(), srcType, declaringClass);
        // (2) 获取通配符泛型的上界数组,如 ? extends Number,获得数组为 { Number }
        Type[] upperBounds = resolveWildcardTypeBounds(wildcardType.getUpperBounds(), srcType, declaringClass);
        return new WildcardTypeImpl(lowerBounds, upperBounds);
      }
    
      private static Type[] resolveWildcardTypeBounds(Type[] bounds, Type srcType, Class<?> declaringClass) {
        Type[] result = new Type[bounds.length];
        // (3) 解析通配符上界或下界中每个界限类型的实际类型
        for (int i = 0; i < bounds.length; i++) {
          // (3.1) 界限类型是一个类型变量,eg: <? extends T>
          if (bounds[i] instanceof TypeVariable) {
            result[i] = resolveTypeVar((TypeVariable<?>) bounds[i], srcType, declaringClass);
          // (3.2) 界限类型是一个参数化类型,eg: <? super ArrayList<T>>
          } else if (bounds[i] instanceof ParameterizedType) {
            result[i] = resolveParameterizedType((ParameterizedType) bounds[i], srcType, declaringClass);
          // (3.3) 界限类型是一个嵌套的通配符类型,递归调用,想象不出有什么类型符合这种例子,
          // 形如 <? extends <? super Interface1> 形式上符合,但不符合语法和语义
          //      <? extends Interface1, Interface2> 表示通配的类型要实现多个接口,形式上也不会走到这个分支
          } else if (bounds[i] instanceof WildcardType) {
            result[i] = resolveWildcardType((WildcardType) bounds[i], srcType, declaringClass);
          // (3.4) 界限类型是一个具体类型,如:<? extends List>
          } else {
            result[i] = bounds[i];
          }
        }
        return result;
      }
    

    【解析】
    (1)获取通配符泛型的下界,如 ? super Long,获得数组为 { Long }
    (2)获取通配符泛型的上界数组,如 ? extends Number,获得数组为 { Number }
    (3)解析通配符上界或下界中每个界限类型的实际类型

    • (3.1)界限类型是一个类型变量,eg: <? extends T>
    • (3.2)界限类型是一个参数化类型,eg: <? super ArrayList<T>>
    • (3.3)界限类型是一个嵌套的通配符类型,递归调用(想象不出有什么类型符合这种例子)
    • (3.4)界限类型是一个具体类型,如:<? extends List>

    8、Type scanSuperTypes(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass, Class<?> clazz, Type superclass)

    【功能】沿着继承链,扫描超类,并从超类的具体类型中解析出 typeVar 的具体类型。
    【源码与注解】

      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();
          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];
                }
              }
            }
          // (1)沿着源类型srcType继承链上溯父类,找到声明了类型变量的父类
          } else if (declaringClass.isAssignableFrom(parentAsClass)) {
            result = resolveTypeVar(typeVar, parentAsType, declaringClass);
          }
        // (2)superClass不带泛型,那么泛型上溯的基类中
        } else if (superclass instanceof Class) {
          if (declaringClass.isAssignableFrom((Class<?>) superclass)) {
            result = resolveTypeVar(typeVar, superclass, declaringClass);
          }
        }
        return result;
      }
    

    【解析】
      没有注释的分支,在上面的两个演示的测试样例中都演示过了,不再赘述,有可能一次沿着继承链上的基类找不到 typeVar 对应的具体类型,那么要继续上溯,知道找到对应的基类,才能解析到具体的类型,如:

    class A<T, S> {
        T t;
        S s;
    }
    class B<S> extends A<String, S> {}
    class C extends B<Integer> {}
    

      类 C 拥有继承来的属性 t,上溯基类解析具体类型时,泛型表示的父类为 B<Integer>,无法解析 T 的具体类型,因此要继续上溯 B<Integer> 的父类 A<String, Integer>,才能解析到为 String,这里的情况其实就对应上面源码注解(1)处的分支。

    class A<T> {
        T t;
    }
    class B extends A<String> {}
    class C extends B {}
    

      换一下代码,类 C 拥有继承来的属性 t,上溯基类解析具体类型时,父类为 B,不带泛型,无法解析 T 的具体类型,因此要继续上溯 B 的父类 A<String>,这里的情况其实就对应上面源码注解(2)处的分支。

    9、Type resolveGenericArrayType(GenericArrayType genericArrayType, Type srcType, Class<?> declaringClass)

    【功能】解析泛型数组类型属性的元素类型的具体类型。
    【代码与注解】

      private static Type resolveGenericArrayType(GenericArrayType genericArrayType, Type srcType, Class<?> declaringClass) {
        // (1) 获取泛型数组的元素类型
        Type componentType = genericArrayType.getGenericComponentType();
        Type resolvedComponentType = null;
        // (2) 元素类型可能是类型变量,如:T[]
        if (componentType instanceof TypeVariable) {
          resolvedComponentType = resolveTypeVar((TypeVariable<?>) componentType, srcType, declaringClass);
        // (3) 元素类型可能是嵌套的泛型数组,如:T[S[]]
        } else if (componentType instanceof GenericArrayType) {
          resolvedComponentType = resolveGenericArrayType((GenericArrayType) componentType, srcType, declaringClass);
        // (4) 元素类型可能是参数化类型,如:T[List<String>]
        } else if (componentType instanceof ParameterizedType) {
          resolvedComponentType = resolveParameterizedType((ParameterizedType) componentType, srcType, declaringClass);
        }
        // (5) 元素类型可能是普通具体类型,如:Integer[]
        if (resolvedComponentType instanceof Class) {
          return Array.newInstance((Class<?>) resolvedComponentType, 0).getClass();
        } else {
          return new GenericArrayTypeImpl(resolvedComponentType);
        }
      }
    

    五、内部包装类

    1、ParameterizedTypeImpl

    【功能】包装包含参数化类型具体类型信息的类。
    【源码】

      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) + "]";
        }
      }
    

    【解析】
      就是一个实现了 ParameterizedType 接口的类,有原始类型、参数类型、类型所属类型三个属性。

    2、WildcardTypeImpl

    【功能】包装通配符泛型具体类型的类。
    【源码】

      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;
        }
      }
    

    【解析】
      实现了 WildcardType 接口,保存通配的界限类型的具体类型信息。

    3、GenericArrayTypeImpl

    【功能】保存泛型数组元素类型的具体类型信息的类。
    【源码】

      static class GenericArrayTypeImpl implements GenericArrayType {
        private Type genericComponentType;
    
        private GenericArrayTypeImpl(Type genericComponentType) {
          super();
          this.genericComponentType = genericComponentType;
        }
    
        @Override
        public Type getGenericComponentType() {
          return genericComponentType;
        }
      }
    

    【解析】
      实现了 GenericArrayType 接口,保存元素具体类型信息。

    PS.入口传入要解析的类型如果可以解析出具体类型,则返回对应的Class对象,否则都用上面三个内部类包装返回,由于类型有可能是嵌套的,所以返回这些包装类时,包装类之间也有可能是嵌套的,所以外部调用程序使用返回的类型时,如果判断到不是Class对象,获取包装的具体类型信息时也要嵌套地去获取具体的类型信息。

    相关文章

      网友评论

        本文标题:[MyBatis源码分析 - 反射器模块 - 组件四] Type

        本文链接:https://www.haomeiwen.com/subject/yxdfmktx.html