MyBatis 源码分析(四):反射模块

前言

上一篇我们了解了Mybatis解析器模块,MyBatis 源码分析(三):解析器模块

本篇我们来了解反射模块。相比 parsing 包来说,reflection 包的代码量大概是 2-3 倍。当然,不要慌,都是比较简单的代码。当然,这是一篇非常非常非常长的博客,如果想要比较好的理解这个模块,一定要基于 MyBatis 提供的这个模块的单元测试,多多调试。

对应 reflection 包。如下图所示:

065e3fa927a44141a268c741463a12d1.png

在 MyBatis源码分析(二):项目结构 中,简单介绍了这个模块:

该模块对 Java 原生的反射进行了良好的封装,提供了更加简洁易用的 API,方便上层使调用,并且对反射操作进行了一系列优化

下面,我们就来看看具体的源码。

2. Reflector

org.apache.ibatis.reflection.Reflector ,反射器,每个 Reflector 对应一个类。Reflector 会缓存反射操作需要的类的信息,例如:构造方法、属性名、setting / getting 方法等等。代码如下:

// Reflector.javapublic class Reflector {/*** 对应的类*/private final Class<?> type;/*** 可读属性数组*/private final String[] readablePropertyNames;/*** 可写属性集合*/private final String[] writeablePropertyNames;/*** 属性对应的 setting 方法的映射。** key 为属性名称* value 为 Invoker 对象*/private final Map<String, Invoker> setMethods = new HashMap<>();/*** 属性对应的 getting 方法的映射。** key 为属性名称* value 为 Invoker 对象*/private final Map<String, Invoker> getMethods = new HashMap<>();/*** 属性对应的 setting 方法的方法参数类型的映射。{@link #setMethods}** key 为属性名称* value 为方法参数类型*/private final Map<String, Class<?>> setTypes = new HashMap<>();/*** 属性对应的 getting 方法的返回值类型的映射。{@link #getMethods}** key 为属性名称* value 为返回值的类型*/private final Map<String, Class<?>> getTypes = new HashMap<>();/*** 默认构造方法*/private Constructor<?> defaultConstructor;/*** 不区分大小写的属性集合*/private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();public Reflector(Class<?> clazz) {// 设置对应的类type = clazz;// <1> 初始化 defaultConstructoraddDefaultConstructor(clazz);// <2> // 初始化 getMethods 和 getTypes ,通过遍历 getting 方法addGetMethods(clazz);// <3> // 初始化 setMethods 和 setTypes ,通过遍历 setting 方法。addSetMethods(clazz);// <4> // 初始化 getMethods + getTypes 和 setMethods + setTypes ,通过遍历 fields 属性。addFields(clazz);// <5> 初始化 readablePropertyNames、writeablePropertyNames、caseInsensitivePropertyMap 属性readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]);writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]);for (String propName : readablePropertyNames) {caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);}for (String propName : writeablePropertyNames) {caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);}}// ... 省略一些方法
}
  • type 属性,每个 Reflector 对应的类。
  • defaultConstructor 属性,默认无参构造方法。在 <1> 处初始化。
  • getMethodsgetTypes 属性,分别为属性对应的 getting 方法getting 方法的返回类型的映射。在 <2> 处初始化。
  • setMethodssetTypes 属性,分别为属性对应的 setting 方法setting 方法的参数类型的映射。在 <3> 处初始化。
  • <4> 处,初始化 getMethods + getTypes 和 setMethods + setTypes ,通过遍历 fields 属性。详细解析。
  • <5> 处,初始化 readablePropertyNameswriteablePropertyNamescaseInsensitivePropertyMap 属性。

2.1 addDefaultConstructor

#addDefaultConstructor(Class<?> clazz) 方法,查找默认无参构造方法。代码如下:

// Reflector.javaprivate void addDefaultConstructor(Class<?> clazz) {// 获得所有构造方法Constructor<?>[] consts = clazz.getDeclaredConstructors();// 遍历所有构造方法,查找无参的构造方法for (Constructor<?> constructor : consts) {// 判断无参的构造方法if (constructor.getParameterTypes().length == 0) {// 设置构造方法可以访问,避免是 private 等修饰符if (canControlMemberAccessible()) {try {constructor.setAccessible(true);} catch (Exception e) {// Ignored. This is only a final precaution, nothing we can do.}}// 如果构造方法可以访问,赋值给 defaultConstructorif (constructor.isAccessible()) {this.defaultConstructor = constructor;}}}
}/*** Checks whether can control member accessible.** 判断,是否可以修改可访问性** @return If can control member accessible, it return {@literal true}* @since 3.5.0*/
public static boolean canControlMemberAccessible() {try {SecurityManager securityManager = System.getSecurityManager();if (null != securityManager) {securityManager.checkPermission(new ReflectPermission("suppressAccessChecks"));}} catch (SecurityException e) {return false;}return true;
}

2.2 addGetMethods

#addGetMethods(Class<?> cls) 方法,初始化 getMethods 和 getTypes ,通过遍历 getting 方法。代码如下:

// Reflector.javaprivate void addGetMethods(Class<?> cls) {// <1> 属性与其 getting 方法的映射。Map<String, List<Method>> conflictingGetters = new HashMap<>();// <2> 获得所有方法Method[] methods = getClassMethods(cls);// <3> 遍历所有方法for (Method method : methods) {// <3.1> 参数大于 0 ,说明不是 getting 方法,忽略if (method.getParameterTypes().length > 0) {continue;}// <3.2> 以 get 和 is 方法名开头,说明是 getting 方法String name = method.getName();if ((name.startsWith("get") && name.length() > 3)|| (name.startsWith("is") && name.length() > 2)) {// <3.3> 获得属性name = PropertyNamer.methodToProperty(name);// <3.4> 添加到 conflictingGetters 中addMethodConflict(conflictingGetters, name, method);}}// <4> 解决 getting 冲突方法resolveGetterConflicts(conflictingGetters);
}
  • <1> 处,conflictingGetters 变量,属性与其 getting 方法的映射。因为父类和子类都可能定义了相同属性的 getting 方法,所以 VALUE 会是个数组。
  • <2> 处,调用 #getClassMethods(Class<?> cls) 方法,获得所有方法。
  • <3> 处,遍历所有方法,挑选符合的 getting 方法,添加到 conflictingGetters 中。

    • <3.1> 处,方法参数大于 0 ,说明不是 getting 方法,忽略。
    • <3.2> 处,方法名以 get 和 is 方法名开头,说明是 getting 方法。
    • <3.3> 处,调用 PropertyNamer#methodToProperty(String name) 方法,获得属性名。
    • <3.4> 处,调用 #addMethodConflict(Map<String, List<Method>> conflictingMethods, String name, Method method) 方法,添加到 conflictingGetters 中。代码如下:

      // Reflector.javaprivate void addMethodConflict(Map<String, List<Method>> conflictingMethods, String name, Method method) {List<Method> list = conflictingMethods.computeIfAbsent(name, k -> new ArrayList<>());list.add(method);
      }
      
      • JDK8 编写这样的逻辑,真心方便。
  • <4> 处,调用 #resolveGetterConflicts(Map<String, List<Method>>) 方法,解决 getting 冲突方法。

2.2.1 getClassMethods

#getClassMethods(Class<?> cls) 方法,获得所有方法。代码如下:

// Reflector.javaprivate Method[] getClassMethods(Class<?> cls) {// 每个方法签名与该方法的映射Map<String, Method> uniqueMethods = new HashMap<>();// 循环类,类的父类,类的父类的父类,直到父类为 ObjectClass<?> currentClass = cls;while (currentClass != null && currentClass != Object.class) {// <1> 记录当前类定义的方法addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());// we also need to look for interface methods -// because the class may be abstract// <2> 记录接口中定义的方法Class<?>[] interfaces = currentClass.getInterfaces();for (Class<?> anInterface : interfaces) {addUniqueMethods(uniqueMethods, anInterface.getMethods());}// 获得父类currentClass = currentClass.getSuperclass();}// 转换成 Method 数组返回Collection<Method> methods = uniqueMethods.values();return methods.toArray(new Method[methods.size()]);
  • <1> 和 <2> 处,会调用 #addUniqueMethods(Map<String, Method> uniqueMethods, Method[] methods) 方法,添加方法数组到 uniqueMethods 中。代码如下:

    // Reflector.javaprivate void addUniqueMethods(Map<String, Method> uniqueMethods, Method[] methods) {for (Method currentMethod : methods) {if (!currentMethod.isBridge()) { // 忽略 bridge 方法,参见 https://www.zhihu.com/question/54895701/answer/141623158 文章// <3> 获得方法签名String signature = getSignature(currentMethod);// check to see if the method is already known// if it is known, then an extended class must have// overridden a method// 当 uniqueMethods 不存在时,进行添加if (!uniqueMethods.containsKey(signature)) {// 设置方法可访问if (canControlMemberAccessible()) {try {currentMethod.setAccessible(true);} catch (Exception e) {// Ignored. This is only a final precaution, nothing we can do.}}// 添加到 uniqueMethods 中uniqueMethods.put(signature, currentMethod);}}}
    }
    
    • <3> 处,会调用 #getSignature(Method method) 方法,获得方法签名。代码如下:

      // Reflector.javaprivate String getSignature(Method method) {StringBuilder sb = new StringBuilder();// 返回类型Class<?> returnType = method.getReturnType();if (returnType != null) {sb.append(returnType.getName()).append('#');}// 方法名sb.append(method.getName());// 方法参数Class<?>[] parameters = method.getParameterTypes();for (int i = 0; i < parameters.length; i++) {if (i == 0) {sb.append(':');} else {sb.append(',');}sb.append(parameters[i].getName());}return sb.toString();
      }
      
      • 格式:returnType#方法名:参数名1,参数名2,参数名3 。
      • 例如:void#checkPackageAccess:java.lang.ClassLoader,boolean 。

2.2.2 resolveGetterConflicts

#resolveGetterConflicts(Map<String, List<Method>>) 方法,解决 getting 冲突方法。最终,一个属性,只保留一个对应的方法。代码如下:

// Reflector.javaprivate void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {// 遍历每个属性,查找其最匹配的方法。因为子类可以覆写父类的方法,所以一个属性,可能对应多个 getting 方法for (Entry<String, List<Method>> entry : conflictingGetters.entrySet()) {Method winner = null; // 最匹配的方法String propName = entry.getKey();for (Method candidate : entry.getValue()) {// winner 为空,说明 candidate 为最匹配的方法if (winner == null) {winner = candidate;continue;}// <1> 基于返回类型比较Class<?> winnerType = winner.getReturnType();Class<?> candidateType = candidate.getReturnType();// 类型相同if (candidateType.equals(winnerType)) {// 返回值了诶选哪个相同,应该在 getClassMethods 方法中,已经合并。所以抛出 ReflectionException 异常if (!boolean.class.equals(candidateType)) {throw new ReflectionException("Illegal overloaded getter method with ambiguous type for property "+ propName + " in class " + winner.getDeclaringClass()+ ". This breaks the JavaBeans specification and can cause unpredictable results.");// 选择 boolean 类型的 is 方法} else if (candidate.getName().startsWith("is")) {winner = candidate;}// 不符合选择子类} else if (candidateType.isAssignableFrom(winnerType)) {// OK getter type is descendant// <1.1> 符合选择子类。因为子类可以修改放大返回值。例如,父类的一个方法的返回值为 List ,子类对该方法的返回值可以覆写为 ArrayList 。} else if (winnerType.isAssignableFrom(candidateType)) {winner = candidate;// <1.2> 返回类型冲突,抛出 ReflectionException 异常} else {throw new ReflectionException("Illegal overloaded getter method with ambiguous type for property "+ propName + " in class " + winner.getDeclaringClass()+ ". This breaks the JavaBeans specification and can cause unpredictable results.");}}// <2> 添加到 getMethods 和 getTypes 中addGetMethod(propName, winner);}
}
  • <1> 处,基于返回类型比较。重点在 <1.1> 和 <1.2> 的情况,因为子类可以修改放大返回值,所以在出现这个情况时,选择子类的该方法。例如,父类的一个方法的返回值为 List ,子类对该方法的返回值可以覆写为 ArrayList 。代码如下:

    public class A {List<String> getXXXX();}public class B extends A {ArrayList<String> getXXXX(); // 选择它}
    
  • <2> 处,调用 #addGetMethod(String name, Method method) 方法,添加方法到 getMethods 和 getTypes 中。代码如下:

    // Reflector.javaprivate void addGetMethod(String name, Method method) {// <2.1> 判断是合理的属性名if (isValidPropertyName(name)) {// <2.2> 添加到 getMethods 中getMethods.put(name, new MethodInvoker(method));// <2.3> 添加到 getTypes 中Type returnType = TypeParameterResolver.resolveReturnType(method, type);getTypes.put(name, typeToClass(returnType));}
    }
    
    • <2.1> 处,调用 #isValidPropertyName(String name) 方法,判断是合理的属性名。代码如下:

      // Reflector.javaprivate boolean isValidPropertyName(String name) {return !(name.startsWith("$") || "serialVersionUID".equals(name) || "class".equals(name));
      }
      
    • <2.2> 处,添加到 getMethods 中。此处,我们可以看到一个 MethodInvoker 类,详细解析。
    • <2.3> 处,添加到 getTypes 中。

      • 此处,我们可以看到一个 TypeParameterResolver 类。
      • #typeToClass(Type src) 方法,获得 java.lang.reflect.Type 对应的类。代码如下:

        // Reflector.javaprivate Class<?> typeToClass(Type src) {Class<?> result = null;// 普通类型,直接使用类if (src instanceof Class) {result = (Class<?>) src;// 泛型类型,使用泛型} else if (src instanceof ParameterizedType) {result = (Class<?>) ((ParameterizedType) src).getRawType();// 泛型数组,获得具体类} else if (src instanceof GenericArrayType) {Type componentType = ((GenericArrayType) src).getGenericComponentType();if (componentType instanceof Class) { // 普通类型result = Array.newInstance((Class<?>) componentType, 0).getClass();} else {Class<?> componentClass = typeToClass(componentType); // 递归该方法,返回类result = Array.newInstance(componentClass, 0).getClass();}}// 都不符合,使用 Object 类if (result == null) {result = Object.class;}return result;
        }
        
        • 代码比较简单,就是寻找 Type 真正对应的类。

2.3 addSetMethods

#addSetMethods(Class<?> cls) 方法,初始化 setMethods 和 setTypes ,通过遍历 setting 方法。代码如下:

// Reflector.javaprivate void addSetMethods(Class<?> cls) {// 属性与其 setting 方法的映射。Map<String, List<Method>> conflictingSetters = new HashMap<>();// 获得所有方法Method[] methods = getClassMethods(cls);// 遍历所有方法for (Method method : methods) {String name = method.getName();// <1> 方法名为 set 开头// 参数数量为 1if (name.startsWith("set") && name.length() > 3) {if (method.getParameterTypes().length == 1) {// 获得属性name = PropertyNamer.methodToProperty(name);// 添加到 conflictingSetters 中addMethodConflict(conflictingSetters, name, method);}}}// <2> 解决 setting 冲突方法resolveSetterConflicts(conflictingSetters);
}
  • 总体逻辑和 #addGetMethods(Class<?> cls) 方法差不多。主要差异点在 <1> 和 <2> 处。因为 <1> 一眼就能明白,所以我们只看 <2> ,调用 #resolveSetterConflicts(Map<String, List<Method>> conflictingSetters) 方法,解决 setting 冲突方法。

2.3.1 resolveSetterConflicts

#resolveSetterConflicts(Map<String, List<Method>> conflictingSetters) 方法,解决 setting 冲突方法。代码如下:

// Reflector.javaprivate void resolveSetterConflicts(Map<String, List<Method>> conflictingSetters) {// 遍历每个属性,查找其最匹配的方法。因为子类可以覆写父类的方法,所以一个属性,可能对应多个 setting 方法for (String propName : conflictingSetters.keySet()) {List<Method> setters = conflictingSetters.get(propName);Class<?> getterType = getTypes.get(propName);Method match = null;ReflectionException exception = null;// <1> 遍历属性对应的 setting 方法for (Method setter : setters) {Class<?> paramType = setter.getParameterTypes()[0];// 和 getterType 相同,直接使用if (paramType.equals(getterType)) {// should be the best matchmatch = setter;break;}if (exception == null) {try {// 选择一个更加匹配的match = pickBetterSetter(match, setter, propName);} catch (ReflectionException e) {// there could still be the 'best match'match = null;exception = e;}}}// <2> 添加到 setMethods 和 setTypes 中if (match == null) {throw exception;} else {addSetMethod(propName, match);}}
}
  • <1> 处,解决冲突 setting 方法的方式,实际和 getting 方法的方式是不太一样的。首先,多的就是考虑了对应的 getterType 为优先级最高。其次,#pickBetterSetter(Method setter1, Method setter2, String property) 方法,选择一个更加匹配的,和 getting 方法是相同的,因为要选择精准的方法。代码如下:

    // Reflector.javaprivate Method pickBetterSetter(Method setter1, Method setter2, String property) {if (setter1 == null) {return setter2;}Class<?> paramType1 = setter1.getParameterTypes()[0];Class<?> paramType2 = setter2.getParameterTypes()[0];if (paramType1.isAssignableFrom(paramType2)) {return setter2;} else if (paramType2.isAssignableFrom(paramType1)) {return setter1;}throw new ReflectionException("Ambiguous setters defined for property '" + property + "' in class '"+ setter2.getDeclaringClass() + "' with types '" + paramType1.getName() + "' and '"+ paramType2.getName() + "'.");
    }
    
  • <2> 处,调用 #addSetMethod(String name, Method method) 方法,添加到 setMethods 和 setTypes 中。代码如下:

    // Reflector.javaprivate void addSetMethod(String name, Method method) {if (isValidPropertyName(name)) {// 添加到 setMethods 中setMethods.put(name, new MethodInvoker(method));// 添加到 setTypes 中Type[] paramTypes = TypeParameterResolver.resolveParamTypes(method, type);setTypes.put(name, typeToClass(paramTypes[0]));}
    }
    
    • 比较简单,和 #addGetMethod(String name, Method method) 方法是类似的。

2.4 addFields

#addFields(Class<?> clazz) 方法,初始化 getMethods + getTypes 和 setMethods + setTypes ,通过遍历 fields 属性。实际上,它是 #addGetMethods(...) 和 #addSetMethods(...) 方法的补充,因为有些 field ,不存在对应的 setting 或 getting 方法,所以直接使用对应的 field ,而不是方法。代码如下:

// Reflector.javaprivate void addFields(Class<?> clazz) {// 获得所有 field 们Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {// 设置 field 可访问if (canControlMemberAccessible()) {try {field.setAccessible(true);} catch (Exception e) {// Ignored. This is only a final precaution, nothing we can do.}}if (field.isAccessible()) {// <1> 添加到 setMethods 和 setTypes 中if (!setMethods.containsKey(field.getName())) {// issue #379 - removed the check for final because JDK 1.5 allows// modification of final fields through reflection (JSR-133). (JGB)// pr #16 - final static can only be set by the classloaderint modifiers = field.getModifiers();if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) {addSetField(field);}}// 添加到 getMethods 和 getTypes 中if (!getMethods.containsKey(field.getName())) {addGetField(field);}}}// 递归,处理父类if (clazz.getSuperclass() != null) {addFields(clazz.getSuperclass());}
}
  • <1> 处,若 setMethods 不存在,则调用 #addSetField(Field field) 方法,添加到 setMethods 和 setTypes 中。代码如下:

    // Reflector.javaprivate void addSetField(Field field) {// 判断是合理的属性if (isValidPropertyName(field.getName())) {// 添加到 setMethods 中setMethods.put(field.getName(), new SetFieldInvoker(field));// 添加到 setTypes 中Type fieldType = TypeParameterResolver.resolveFieldType(field, type);setTypes.put(field.getName(), typeToClass(fieldType));}
    }
    
    • 注意,此处创建的是 SetFieldInvoker 对象。
  • <2> 处,若 getMethods 不存在,则调用 #addGetField(Field field) 方法,添加到 getMethods 和 getTypes 中。代码如下:

    // Reflector.javaprivate void addGetField(Field field) {// 判断是合理的属性if (isValidPropertyName(field.getName())) {// 添加到 getMethods 中getMethods.put(field.getName(), new GetFieldInvoker(field));// 添加到 getMethods 中Type fieldType = TypeParameterResolver.resolveFieldType(field, type);getTypes.put(field.getName(), typeToClass(fieldType));}
    }
    
    • 注意,此处创建的是 GetFieldInvoker 对象。详细解析。

2.5 其它方法

Reflector 中,还有其它方法,用于对它的属性进行访问,例如:

// Reflector.javapublic Invoker getSetInvoker(String propertyName) {Invoker method = setMethods.get(propertyName);if (method == null) {throw new ReflectionException("There is no setter for property named '" + propertyName + "' in '" + type + "'");}return method;
}

3. ReflectorFactory

org.apache.ibatis.reflection.ReflectorFactory ,Reflector 工厂接口,用于创建和缓存 Reflector 对象。代码如下:

// ReflectorFactory.javapublic interface ReflectorFactory {/*** @return 是否缓存 Reflector 对象*/boolean isClassCacheEnabled();/*** 设置是否缓存 Reflector 对象** @param classCacheEnabled 是否缓存*/void setClassCacheEnabled(boolean classCacheEnabled);/*** 获取 Reflector 对象** @param type 指定类* @return Reflector 对象*/Reflector findForClass(Class<?> type);}

3.1 DefaultReflectorFactory

org.apache.ibatis.reflection.DefaultReflectorFactory ,实现 ReflectorFactory 接口,默认的 ReflectorFactory 实现类。代码如下:

// DefaultReflectorFactory.javapublic class DefaultReflectorFactory implements ReflectorFactory {/*** 是否缓存*/private boolean classCacheEnabled = true;/*** Reflector 的缓存映射** KEY:类* VALUE:Reflector 对象*/private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap<>();public DefaultReflectorFactory() {}@Overridepublic boolean isClassCacheEnabled() {return classCacheEnabled;}@Overridepublic void setClassCacheEnabled(boolean classCacheEnabled) {this.classCacheEnabled = classCacheEnabled;}@Overridepublic Reflector findForClass(Class<?> type) {// 开启缓存,则从 reflectorMap 中获取if (classCacheEnabled) {// synchronized (type) removed see issue #461return reflectorMap.computeIfAbsent(type, Reflector::new); // 不存在,则进行创建// 关闭缓存,则创建 Reflector 对象} else {return new Reflector(type);}}}

4. Invoker

org.apache.ibatis.reflection.invoker.Invoker ,调用者接口。代码如下:

// Invoker.javapublic interface Invoker {/*** 执行调用** @param target 目标* @param args 参数* @return 结果* @throws IllegalAccessException* @throws InvocationTargetException*/Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;/*** @return 类*/Class<?> getType();}
  • 核心是 #invoke(Object target, Object[] args) 方法,执行一次调用。而具体调用什么方法,由子类来实现。

4.1 GetFieldInvoker

org.apache.ibatis.reflection.invoker.GetFieldInvoker ,实现 Invoker 接口,获得 Field 调用者。代码如下:

// GetFieldInvoker.javapublic class GetFieldInvoker implements Invoker {/*** Field 对象*/private final Field field;public GetFieldInvoker(Field field) {this.field = field;}// 获得属性@Overridepublic Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {return field.get(target);}// 返回属性类型@Overridepublic Class<?> getType() {return field.getType();}}

4.2 SetFieldInvoker

org.apache.ibatis.reflection.invoker.SetFieldInvoker ,实现 Invoker 接口,设置 Field 调用者。代码如下:

// SetFieldInvoker.javapublic class SetFieldInvoker implements Invoker {/*** Field 对象*/private final Field field;public SetFieldInvoker(Field field) {this.field = field;}// 设置 Field 属性@Overridepublic Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {field.set(target, args[0]);return null;}// 返回属性类型@Overridepublic Class<?> getType() {return field.getType();}}

4.3 MethodInvoker

org.apache.ibatis.reflection.invoker.MethodInvoker ,实现 Invoker 接口,指定方法的调用器。代码如下:

// MethodInvoker.javapublic class MethodInvoker implements Invoker {/*** 类型*/private final Class<?> type;/*** 指定方法*/private final Method method;public MethodInvoker(Method method) {this.method = method;// 参数大小为 1 时,一般是 setting 方法,设置 type 为方法参数[0]if (method.getParameterTypes().length == 1) {type = method.getParameterTypes()[0];// 否则,一般是 getting 方法,设置 type 为返回类型} else {type = method.getReturnType();}}// 执行指定方法@Overridepublic Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {return method.invoke(target, args);}@Overridepublic Class<?> getType() {return type;}}

5. ObjectFactory

org.apache.ibatis.reflection.factory.ObjectFactory ,Object 工厂接口,用于创建指定类的对象。代码如下:

// ObjectFactory.javapublic interface ObjectFactory {/*** 设置 Properties** Sets configuration properties.* @param properties configuration properties*/void setProperties(Properties properties);/*** 创建指定类的对象,使用默认构造方法** Creates a new object with default constructor.* @param type Object type* @return 对象*/<T> T create(Class<T> type);/*** Creates a new object with the specified constructor and params.** 创建指定类的对象,使用特定的构造方法** @param type Object type* @param constructorArgTypes Constructor argument types 指定构造方法的参数列表* @param constructorArgs Constructor argument values 参数数组* @return 对象*/<T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);/*** Returns true if this object can have a set of other objects.* It's main purpose is to support non-java.util.Collection objects like Scala collections.** 判断指定类是否为集合类** @param type Object type* @return whether it is a collection or not* @since 3.1.0*/<T> boolean isCollection(Class<T> type);}
  • 比较简单,一共有三类方法。

5.1 DefaultObjectFactory

org.apache.ibatis.reflection.factory.DefaultObjectFactory ,实现 ObjectFactory、Serializable 接口,默认 ObjectFactory 实现类。

5.1.1 create

#create(Class<T> type, ...) 方法,创建指定类的对象。代码如下:

// DefaultObjectFactory.java@Override
public <T> T create(Class<T> type) {return create(type, null, null);
}@SuppressWarnings("unchecked")
@Override
public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {// <1> 获得需要创建的类Class<?> classToCreate = resolveInterface(type);// we know types are assignable// <2> 创建指定类的对象return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
}
  • <1> 处,调用 #resolveInterface(Class<?> type) 方法,获得需要创建的类。代码如下:

    // DefaultObjectFactory.javaprotected Class<?> resolveInterface(Class<?> type) {Class<?> classToCreate;if (type == List.class || type == Collection.class || type == Iterable.class) {classToCreate = ArrayList.class;} else if (type == Map.class) {classToCreate = HashMap.class;} else if (type == SortedSet.class) { // issue #510 Collections SupportclassToCreate = TreeSet.class;} else if (type == Set.class) {classToCreate = HashSet.class;} else {classToCreate = type;}return classToCreate;
    }
    
    • 对于我们常用的集合接口,返回对应的实现类。
  • <1> 处,调用 #instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) 方法,创建指定类的对象。代码如下:

    // DefaultObjectFactory.javaprivate <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {try {Constructor<T> constructor;// <x1> 通过无参构造方法,创建指定类的对象if (constructorArgTypes == null || constructorArgs == null) {constructor = type.getDeclaredConstructor();if (!constructor.isAccessible()) {constructor.setAccessible(true);}return constructor.newInstance();}// <x2> 使用特定构造方法,创建指定类的对象constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()]));if (!constructor.isAccessible()) {constructor.setAccessible(true);}return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));} catch (Exception e) {// 拼接 argTypesStringBuilder argTypes = new StringBuilder();if (constructorArgTypes != null && !constructorArgTypes.isEmpty()) {for (Class<?> argType : constructorArgTypes) {argTypes.append(argType.getSimpleName());argTypes.append(",");}argTypes.deleteCharAt(argTypes.length() - 1); // remove trailing ,}// 拼接 argValuesStringBuilder argValues = new StringBuilder();if (constructorArgs != null && !constructorArgs.isEmpty()) {for (Object argValue : constructorArgs) {argValues.append(String.valueOf(argValue));argValues.append(",");}argValues.deleteCharAt(argValues.length() - 1); // remove trailing ,}// 抛出 ReflectionException 异常throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);}
    }
    
    • 代码比较简单,分成 <x1><x2> 两种情况。

5.1.2 isCollection

#isCollection(Class<T> type) 方法,判断指定类是否为集合类。代码如下:

// DefaultObjectFactory.java@Override
public <T> boolean isCollection(Class<T> type) {return Collection.class.isAssignableFrom(type);
}
  • 判断是否为 java.util.Collection 的子类。

5.1.3 setProperties

#setProperties(Properties properties) 方法,设置 Properties 。代码如下:

// DefaultObjectFactory.java@Override
public void setProperties(Properties properties) {// no props for default
}
  • 目前是个空实现。所以,暂时可以忽略这个方法。

6. Property 工具类

org.apache.ibatis.reflection.property 包下,提供了 PropertyCopier、PropertyNamer、PropertyTokenizer 三个属性相关的工具类。接下来,我们逐小节来解析。

6.1 PropertyCopier

org.apache.ibatis.reflection.property.PropertyCopier ,属性复制器。代码如下:

// PropertyNamer.javapublic final class PropertyCopier {private PropertyCopier() {// Prevent Instantiation of Static Class}/*** 将 sourceBean 的属性,复制到 destinationBean 中** @param type 指定类* @param sourceBean 来源 Bean 对象* @param destinationBean 目标 Bean 对象*/public static void copyBeanProperties(Class<?> type, Object sourceBean, Object destinationBean) {// 循环,从当前类开始,不断复制到父类,直到父类不存在Class<?> parent = type;while (parent != null) {// 获得当前 parent 类定义的属性final Field[] fields = parent.getDeclaredFields();for (Field field : fields) {try {// 设置属性可访问field.setAccessible(true);// 从 sourceBean 中,复制到 destinationBean 去field.set(destinationBean, field.get(sourceBean));} catch (Exception e) {// Nothing useful to do, will only fail on final fields, which will be ignored.}}// 获得父类parent = parent.getSuperclass();}}}

6.2 PropertyNamer

org.apache.ibatis.reflection.property.PropertyNamer ,属性名相关的工具类方法。代码如下:

public final class PropertyNamer {private PropertyNamer() {// Prevent Instantiation of Static Class}/*** 根据方法名,获得对应的属性名** @param name 方法名* @return 属性名*/public static String methodToProperty(String name) {// is 方法if (name.startsWith("is")) {name = name.substring(2);// get 或者 set 方法} else if (name.startsWith("get") || name.startsWith("set")) {name = name.substring(3);// 抛出 ReflectionException 异常,因为只能处理 is、set、get 方法} else {throw new ReflectionException("Error parsing property name '" + name + "'.  Didn't start with 'is', 'get' or 'set'.");}// 首字母小写if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);}return name;}/*** 判断是否为 is、get、set 方法** @param name 方法名* @return 是否*/public static boolean isProperty(String name) {return name.startsWith("get") || name.startsWith("set") || name.startsWith("is");}/*** 判断是否为 get、is 方法** @param name 方法名* @return 是否*/public static boolean isGetter(String name) {return name.startsWith("get") || name.startsWith("is");}/*** 判断是否为 set 方法** @param name 方法名* @return 是否*/public static boolean isSetter(String name) {return name.startsWith("set");}}

6.3 PropertyTokenizer

org.apache.ibatis.reflection.property.PropertyTokenizer ,实现 Iterator 接口,属性分词器,支持迭代器的访问方式。

举个例子,在访问 "order[0].item[0].name" 时,我们希望拆分成 "order[0]""item[0]""name" 三段,那么就可以通过 PropertyTokenizer 来实现。

6.3.1 构造方法

// PropertyTokenizer.java/*** 当前字符串*/
private String name;
/*** 索引的 {@link #name} ,因为 {@link #name} 如果存在 {@link #index} 会被更改*/
private final String indexedName;
/*** 编号。** 对于数组 name[0] ,则 index = 0* 对于 Map map[key] ,则 index = key*/
private String index;
/*** 剩余字符串*/
private final String children;public PropertyTokenizer(String fullname) {// <1> 初始化 name、children 字符串,使用 . 作为分隔int delim = fullname.indexOf('.');if (delim > -1) {name = fullname.substring(0, delim);children = fullname.substring(delim + 1);} else {name = fullname;children = null;}// <2> 记录当前 nameindexedName = name;// 若存在 [ ,则获得 index ,并修改 name 。delim = name.indexOf('[');if (delim > -1) {index = name.substring(delim + 1, name.length() - 1);name = name.substring(0, delim);}
}
  • name 属性,当前字符串。
  • children 属性,剩余字符串。
  • <1> 处,初始化 namechildren 字符串,使用 '.' 作为分隔。
  • indexedName 属性,索引的 name 属性,因为 name 如果存在 index 会被更改。
  • <2> 处,记录当前 name 。
  • index 属性,编号。分成两种情况:
    • name 为数组 item[0] 时,则 index 为 "0" 。
    • name 为 Map map[key] 时,则 index 为 "key" 。
  • <3> 处,初始化 index ,并修改 name 字符串,使用 '[' 作为分隔符。

6.3.2 next

#next() 方法,迭代获得下一个 PropertyTokenizer 对象。代码如下:

// PropertyTokenizer.java@Override
public PropertyTokenizer next() {return new PropertyTokenizer(children);
}
  • 酱紫,它又会执行「6.3.1 构造方法」 的流程。

6.3.3 hasNext

#hasNext() 方法,判断是否有下一个元素。代码如下:

// PropertyTokenizer.javapublic String getChildren() {return children;
}

6.3.4 其它方法

PropertyTokenizer 中,还有其它方法,比较简单,感兴趣的同学,自己研究下哦。

7. MetaClass

org.apache.ibatis.reflection.MetaClass ,类的元数据,基于 Reflector 和 PropertyTokenizer ,提供对指定类的各种骚操作。

7.1 构造方法

// MetaClass.javaprivate final ReflectorFactory reflectorFactory;
private final Reflector reflector;private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {this.reflectorFactory = reflectorFactory;this.reflector = reflectorFactory.findForClass(type);
}
  • 通过构造方法,我们可以看出,一个 MetaClass 对象,对应一个 Class 对象。

目前有两个方法会涉及到调用该构造方法:

  • ① #forClass(Class<?> type, ReflectorFactory reflectorFactory) 静态方法,创建指定类的 MetaClass 对象。代码如下:

    // MetaClass.javapublic static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {return new MetaClass(type, reflectorFactory);
    }
    
  • ② #metaClassForProperty(String name) 方法,创建类的指定属性的类的 MetaClass 对象。代码如下:

    // MetaClass.javapublic MetaClass metaClassForProperty(String name) {// 获得属性的类Class<?> propType = reflector.getGetterType(name);// 创建 MetaClass 对象return MetaClass.forClass(propType, reflectorFactory);
    }
    

7.2 findProperty

#findProperty(String name, boolean useCamelCaseMapping) 方法,根据表达式,获得属性。代码如下:

// MetaClass.javapublic String findProperty(String name, boolean useCamelCaseMapping) {// <1> 下划线转驼峰if (useCamelCaseMapping) {name = name.replace("_", "");}// <2> 获得属性return findProperty(name);
}
  • useCamelCaseMapping 属性,是否要下划线转驼峰 。但是,在 <1> 处,我们仅仅看到 _ 被替换成了空串。这是为什么呢?继续往下看。
  • <2> 处,调用 #findProperty(String name) 方法,根据表达式,获得属性。代码如下:

    // MetaClass.javapublic String findProperty(String name) {// <3> 构建属性StringBuilder prop = buildProperty(name, new StringBuilder());return prop.length() > 0 ? prop.toString() : null;
    }
    
    • <3> 处,调用 #buildProperty(String name, StringBuilder builder) 方法,构建属性。代码如下:
 
// MetaClass.javaprivate StringBuilder buildProperty(String name, StringBuilder builder) {// 创建 PropertyTokenizer 对象,对 name 进行分词PropertyTokenizer prop = new PropertyTokenizer(name);// 有子表达式if (prop.hasNext()) {// <4> 获得属性名,并添加到 builder 中String propertyName = reflector.findPropertyName(prop.getName());if (propertyName != null) {// 拼接属性到 builder 中builder.append(propertyName);builder.append(".");// 创建 MetaClass 对象MetaClass metaProp = metaClassForProperty(propertyName);// 递归解析子表达式 children ,并将结果添加到 builder 中metaProp.buildProperty(prop.getChildren(), builder);}// 无子表达式} else {// <4> 获得属性名,并添加到 builder 中String propertyName = reflector.findPropertyName(name);if (propertyName != null) {builder.append(propertyName);}}return builder;
}

* 创建 PropertyTokenizer 对象,对 `name` 进行**分词**。当有子表达式,继续递归调用 `#buildProperty(String name, StringBuilder builder)` 方法,并将结果添加到 `builder` 中;否则,结束,直接添加到 `builder` 中。 * 在两个 `<4>` 处,解决“下划线转驼峰”的关键是,通过 `Reflector.caseInsensitivePropertyMap` 属性,忽略大小写。代码如下:

// Reflector.java/*** 不区分大小写的属性集合*/
private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();public String findPropertyName(String name) {return caseInsensitivePropertyMap.get(name.toUpperCase(Locale.ENGLISH));
}

7.3 hasGetter

#hasGetter(String name) 方法,判断指定属性是否有 getting 方法。代码如下:

// MetaClass.javapublic boolean hasGetter(String name) {// 创建 PropertyTokenizer 对象,对 name 进行分词PropertyTokenizer prop = new PropertyTokenizer(name);// 有子表达式if (prop.hasNext()) {// 判断是否有该属性的 getting 方法if (reflector.hasGetter(prop.getName())) {// <1> 创建 MetaClass 对象MetaClass metaProp = metaClassForProperty(prop);// 递归判断子表达式 children ,是否有 getting 方法return metaProp.hasGetter(prop.getChildren());} else {return false;}// 无子表达式} else {// 判断是否有该属性的 getting 方法return reflector.hasGetter(prop.getName());}
}
  • <1> 处,调用 #metaClassForProperty(PropertyTokenizer prop) 方法,创建 创建 MetaClass 对象。代码如下:

    // MetaClass.javaprivate MetaClass metaClassForProperty(PropertyTokenizer prop) {// 【调用】获得 getting 方法返回的类型Class<?> propType = getGetterType(prop);// 创建 MetaClass 对象return MetaClass.forClass(propType, reflectorFactory);
    }private Class<?> getGetterType(PropertyTokenizer prop) {// 获得返回类型Class<?> type = reflector.getGetterType(prop.getName());// 如果获取数组的某个位置的元素,则获取其泛型。例如说:list[0].field ,那么就会解析 list 是什么类型,这样才好通过该类型,继续获得 fieldif (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {// 【调用】获得返回的类型Type returnType = getGenericGetterType(prop.getName());// 如果是泛型,进行解析真正的类型if (returnType instanceof ParameterizedType) {Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();if (actualTypeArguments != null && actualTypeArguments.length == 1) { // 为什么这里判断大小为 1 呢,因为 Collection 是 Collection<T> ,至多一个。returnType = actualTypeArguments[0];if (returnType instanceof Class) {type = (Class<?>) returnType;} else if (returnType instanceof ParameterizedType) {type = (Class<?>) ((ParameterizedType) returnType).getRawType();}}}}return type;
    }private Type getGenericGetterType(String propertyName) {try {// 获得 Invoker 对象Invoker invoker = reflector.getGetInvoker(propertyName);// 如果 MethodInvoker 对象,则说明是 getting 方法,解析方法返回类型if (invoker instanceof MethodInvoker) {Field _method = MethodInvoker.class.getDeclaredField("method");_method.setAccessible(true);Method method = (Method) _method.get(invoker);return TypeParameterResolver.resolveReturnType(method, reflector.getType());// 如果 GetFieldInvoker 对象,则说明是 field ,直接访问} else if (invoker instanceof GetFieldInvoker) {Field _field = GetFieldInvoker.class.getDeclaredField("field");_field.setAccessible(true);Field field = (Field) _field.get(invoker);return TypeParameterResolver.resolveFieldType(field, reflector.getType());}} catch (NoSuchFieldException | IllegalAccessException ignored) {}return null;
    }
    
    • 代码比较长,但是注释写的很清楚哦。另外,每个上面的方法, 会调用下面的方法,也就说 metaClassForProperty => getGetterType => getGenericGetterType 。

另外,#hasSetter(String name) 方法,判断指定属性是否有 setting 方法。逻辑上,和 #hasGetter(String name) 方法类似。

7.4 getGetterType

#getGetterType(String name) 方法,获得指定属性的 getting 方法的返回值的类型。代码如下:

// MetaClass.javapublic Class<?> getGetterType(String name) {// 创建 PropertyTokenizer 对象,对 name 进行分词PropertyTokenizer prop = new PropertyTokenizer(name);// 有子表达式if (prop.hasNext()) {// 创建 MetaClass 对象MetaClass metaProp = metaClassForProperty(prop);// 递归判断子表达式 children ,获得返回值的类型return metaProp.getGetterType(prop.getChildren());}// issue #506. Resolve the type inside a Collection Object// 直接获得返回值的类型return getGetterType(prop);
}
  • 和 #hasGetter(String name) 方法类似。

另外,#getSetterType(String name) 方法,判断指定属性是否有 setting 方法。逻辑上,和 #getGetterType(String name) 方法类似。

7.5 其它方法

MetaClass 还有其它方法,比较简单,是基于 Reflector 方法的封装。

8. ObjectWrapper

org.apache.ibatis.reflection.wrapper.ObjectWrapper ,对象包装器接口,基于 MetaClass 工具类,定义对指定对象的各种操作。或者可以说,ObjectWrapper 是 MetaClass 的指定类的具象化。代码如下:

// ObjectWrapper.javapublic interface ObjectWrapper {/*** 获得值** @param prop PropertyTokenizer 对象,相当于键* @return 值*/Object get(PropertyTokenizer prop);/*** 设置值** @param prop PropertyTokenizer 对象,相当于键* @param value 值*/void set(PropertyTokenizer prop, Object value);/*** {@link MetaClass#findProperty(String, boolean)}*/String findProperty(String name, boolean useCamelCaseMapping);/*** {@link MetaClass#getGetterNames()}*/String[] getGetterNames();/*** {@link MetaClass#getSetterNames()}*/String[] getSetterNames();/*** {@link MetaClass#getSetterType(String)}*/Class<?> getSetterType(String name);/*** {@link MetaClass#getGetterType(String)}*/Class<?> getGetterType(String name);/*** {@link MetaClass#hasSetter(String)}*/boolean hasSetter(String name);/*** {@link MetaClass#hasGetter(String)}*/boolean hasGetter(String name);/*** {@link MetaObject#forObject(Object, ObjectFactory, ObjectWrapperFactory, ReflectorFactory)}*/MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory);/*** 是否为集合*/boolean isCollection();/*** 添加元素到集合*/void add(Object element);/*** 添加多个元素到集合*/<E> void addAll(List<E> element);}
  • 从接口中,我们可以看到,主要是对 MetaObject 方法的调用。

ObjectWrapper 的子类实现如下图:

524fc215a6f8b87e4c4fa1d3f7a67bc6.png

ObjectWrapper 类图

8.1 BaseWrapper

org.apache.ibatis.reflection.wrapper.BaseWrapper ,实现 ObjectWrapper 接口,ObjectWrapper 抽象类,为子类 BeanWrapper 和 MapWrapper 提供属性值的获取和设置的公用方法。代码如下:

// BaseWrapper.javapublic abstract class BaseWrapper implements ObjectWrapper {protected static final Object[] NO_ARGUMENTS = new Object[0];/*** MetaObject 对象*/protected final MetaObject metaObject;protected BaseWrapper(MetaObject metaObject) {this.metaObject = metaObject;}/*** 获得指定属性的值** @param prop PropertyTokenizer 对象* @param object 指定 Object 对象* @return 值*/protected Object resolveCollection(PropertyTokenizer prop, Object object) {if ("".equals(prop.getName())) {return object;} else {return metaObject.getValue(prop.getName());}}/*** 获得集合中指定位置的值** @param prop PropertyTokenizer 对象* @param collection 集合* @return 值*/protected Object getCollectionValue(PropertyTokenizer prop, Object collection) {if (collection instanceof Map) {return ((Map) collection).get(prop.getIndex());} else {int i = Integer.parseInt(prop.getIndex());if (collection instanceof List) {return ((List) collection).get(i);} else if (collection instanceof Object[]) {return ((Object[]) collection)[i];} else if (collection instanceof char[]) {return ((char[]) collection)[i];} else if (collection instanceof boolean[]) {return ((boolean[]) collection)[i];} else if (collection instanceof byte[]) {return ((byte[]) collection)[i];} else if (collection instanceof double[]) {return ((double[]) collection)[i];} else if (collection instanceof float[]) {return ((float[]) collection)[i];} else if (collection instanceof int[]) {return ((int[]) collection)[i];} else if (collection instanceof long[]) {return ((long[]) collection)[i];} else if (collection instanceof short[]) {return ((short[]) collection)[i];} else {throw new ReflectionException("The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");}}}/*** 设置集合中指定位置的值** @param prop PropertyTokenizer 对象* @param collection 集合* @param value 值*/protected void setCollectionValue(PropertyTokenizer prop, Object collection, Object value) {if (collection instanceof Map) {((Map) collection).put(prop.getIndex(), value);} else {int i = Integer.parseInt(prop.getIndex());if (collection instanceof List) {((List) collection).set(i, value);} else if (collection instanceof Object[]) {((Object[]) collection)[i] = value;} else if (collection instanceof char[]) {((char[]) collection)[i] = (Character) value;} else if (collection instanceof boolean[]) {((boolean[]) collection)[i] = (Boolean) value;} else if (collection instanceof byte[]) {((byte[]) collection)[i] = (Byte) value;} else if (collection instanceof double[]) {((double[]) collection)[i] = (Double) value;} else if (collection instanceof float[]) {((float[]) collection)[i] = (Float) value;} else if (collection instanceof int[]) {((int[]) collection)[i] = (Integer) value;} else if (collection instanceof long[]) {((long[]) collection)[i] = (Long) value;} else if (collection instanceof short[]) {((short[]) collection)[i] = (Short) value;} else {throw new ReflectionException("The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");}}}}

8.1.1 BeanWrapper

org.apache.ibatis.reflection.wrapper.BeanWrapper ,继承 BaseWrapper 抽象类,普通对象的 ObjectWrapper 实现类,例如 User、Order 这样的 POJO 类。属性如下:

// BeanWrapper.java/*** 普通对象*/
private final Object object;
private final MetaClass metaClass;public BeanWrapper(MetaObject metaObject, Object object) {super(metaObject);this.object = object;// 创建 MetaClass 对象this.metaClass = MetaClass.forClass(object.getClass(), metaObject.getReflectorFactory());
}

8.1.1.1 get

#get(PropertyTokenizer prop) 方法,获得指定属性的值。代码如下:

// BeanWrapper.java@Override
public Object get(PropertyTokenizer prop) {// <1> 获得集合类型的属性的指定位置的值if (prop.getIndex() != null) {// 获得集合类型的属性Object collection = resolveCollection(prop, object);// 获得指定位置的值return getCollectionValue(prop, collection);// <2> 获得属性的值} else {return getBeanProperty(prop, object);}
}
  • <1> 处,获得集合类型的属性的指定位置的值。例如说:User 对象的 list[0] 。所调用的方法,都是 BaseWrapper 所提供的公用方法。
  • <2> 处,调用 #getBeanProperty(PropertyTokenizer prop, Object object) 方法,获得属性的值。代码如下:

    // BeanWrapper.javaprivate Object getBeanProperty(PropertyTokenizer prop, Object object) {try {Invoker method = metaClass.getGetInvoker(prop.getName());try {return method.invoke(object, NO_ARGUMENTS);} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable(t);}} catch (RuntimeException e) {throw e;} catch (Throwable t) {throw new ReflectionException("Could not get property '" + prop.getName() + "' from " + object.getClass() + ".  Cause: " + t.toString(), t);}
    }
    
    • 通过调用 Invoker 方法,获得属性的值。

8.1.1.2 set

#set(PropertyTokenizer prop, Object value) 方法,设置指定属性的值。代码如下:

// BeanWrapper.java@Override
public void set(PropertyTokenizer prop, Object value) {// 设置集合类型的属性的指定位置的值if (prop.getIndex() != null) {// 获得集合类型的属性Object collection = resolveCollection(prop, object);// 设置指定位置的值setCollectionValue(prop, collection, value);// 设置属性的值} else {setBeanProperty(prop, object, value);}
}private void setBeanProperty(PropertyTokenizer prop, Object object, Object value) {try {Invoker method = metaClass.getSetInvoker(prop.getName());Object[] params = {value};try {method.invoke(object, params);} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable(t);}} catch (Throwable t) {throw new ReflectionException("Could not set property '" + prop.getName() + "' of '" + object.getClass() + "' with value '" + value + "' Cause: " + t.toString(), t);}
}

8.1.1.3 getGetterType

#getGetterType(String name) 方法,获得指定属性的 getting 方法的返回值。代码如下:

// BeanWrapper.java@Override
public Class<?> getGetterType(String name) {// 创建 PropertyTokenizer 对象,对 name 进行分词PropertyTokenizer prop = new PropertyTokenizer(name);// 有子表达式if (prop.hasNext()) {// <1> 创建 MetaObject 对象MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());// 如果 metaValue 为空,则基于 metaClass 获得返回类型if (metaValue == SystemMetaObject.NULL_META_OBJECT) {return metaClass.getGetterType(name);// 如果 metaValue 非空,则基于 metaValue 获得返回类型。// 例如:richType.richMap.nihao ,其中 richMap 是 Map 类型,而 nihao 的类型,需要获得到 nihao 的具体值,才能做真正的判断。} else {// 递归判断子表达式 children ,获得返回值的类型return metaValue.getGetterType(prop.getChildren());}// 有子表达式} else {// 直接获得返回值的类型return metaClass.getGetterType(name);}
}
  • 大体逻辑和 MetaClass 的 #getGetterType(String name) 方法是一致的。差异点主要在 <1> 处。
  • <1> 处,基于当前属性,创建 MetaObject 对象。如果该属性对应的值为空,那么 metaValue 会等于 SystemMetaObject.NULL_META_OBJECT 。也因为为空,那么就不能基于 metaValue 去做递归,获取返回值的类型。
  • 当然,以上说起来比较绕,可以添加如下测试用例,跑一次就大体明白了。代码如下:

    @Test
    public void test01() {RichType object = new RichType();if (true) {object.setRichType(new RichType());object.getRichType().setRichMap(new HashMap());object.getRichType().getRichMap().put("nihao", "123");}MetaObject meta = MetaObject.forObject(object, SystemMetaObject.DEFAULT_OBJECT_FACTORY, new CustomBeanWrapperFactory(), new DefaultReflectorFactory());Class<?> clazz = meta.getObjectWrapper().getGetterType("richType.richMap.nihao");System.out.println(clazz);
    }
    
    • 这个测试用例,就是笔者在代码注释上添加的“例如:richType.richMap.nihao ,其中 richMap 是 Map 类型,而 nihao 的类型,需要获得到 nihao 的具体值,才能做真正的判断。”

#getSetterType(String name) 方法,获得指定属性的 setting 方法的方法参数。逻辑上和 #getGetterType(String name) 方法类似的。

8.1.1.6 hasGetter

#hasGetter(String name) 方法,是否有指定属性的 getting 方法。代码如下:

// BeanWrapper.java@Override
public boolean hasGetter(String name) {// 创建 PropertyTokenizer 对象,对 name 进行分词PropertyTokenizer prop = new PropertyTokenizer(name);// 有子表达式if (prop.hasNext()) {// 判断是否有该属性的 getting 方法if (metaClass.hasGetter(prop.getIndexedName())) {// 创建 MetaObject 对象MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());// 如果 metaValue 为空,则基于 metaClass 判断是否有该属性的 getting 方法if (metaValue == SystemMetaObject.NULL_META_OBJECT) {return metaClass.hasGetter(name);// 如果 metaValue 非空,则基于 metaValue 判断是否有 getting 方法。} else {// 递归判断子表达式 children ,判断是否有 getting 方法return metaValue.hasGetter(prop.getChildren());}} else {return false;}// 有子表达式} else {// 判断是否有该属性的 getting 方法return metaClass.hasGetter(name);}
}

和 #getGetterType(String name) 方法类似。


#hasSetter(String name) 方法,判断指定属性是否有 setting 方法的方法。逻辑上和 #hasGetter(String name) 方法类似的。

8.1.1.5 instantiatePropertyValue

#instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) 方法,创建指定属性的值。代码如下:

// BeanWrapper.java@Override
public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {MetaObject metaValue;// 获得 setting 方法的方法参数类型Class<?> type = getSetterType(prop.getName());try {// 创建对象Object newObject = objectFactory.create(type);// 创建 MetaObject 对象metaValue = MetaObject.forObject(newObject, metaObject.getObjectFactory(), metaObject.getObjectWrapperFactory(), metaObject.getReflectorFactory());// <1> 设置当前对象的值set(prop, newObject);} catch (Exception e) {throw new ReflectionException("Cannot set value of property '" + name + "' because '" + name + "' is null and cannot be instantiated on instance of " + type.getName() + ". Cause:" + e.toString(), e);}return metaValue;
}
  • <1> 处,调用 #set(PropertyTokenizer prop, Object value) 方法,设置 newObject 到当前对象的 prop 属性种。
  • 关于这个方法,可能比较难理解,可以调试下 MetaObjectTest#shouldGetAndSetNestedMapPairUsingArraySyntax() 这个单元测试方法。

8.1.1.6 isCollection

#isCollection() 方法,返回 false ,表示不是集合。代码如下:

// BeanWrapper.java@Override
public boolean isCollection() {return false;
}

因此,#add(Object element) 和 #addAll(List<E> list) 方法都是不支持的,直接抛出 UnsupportedOperationException 异常。代码如下:

// BeanWrapper.java@Override
public void add(Object element) {throw new UnsupportedOperationException();
}@Override
public <E> void addAll(List<E> list) {throw new UnsupportedOperationException();
}

8.1.2 MapWrapper

org.apache.ibatis.reflection.wrapper.MapWrapper ,继承 BaseWrapper 抽象类,Map 对象的 ObjectWrapper 实现类。

MapWrapper 和 BeanWrapper 的大体逻辑是一样的,差异点主要如下:

// MapWrapper.java// object 变成了 map
private final Map<String, Object> map;// 属性的操作变成了
map.put(prop.getName(), value);
map.get(prop.getName());

8.2 CollectionWrapper

org.apache.ibatis.reflection.wrapper.CollectionWrapper ,实现 ObjectWrapper 接口,集合 ObjectWrapper 实现类。比较简单,直接看代码:

// CollectionWrapper.javapublic class CollectionWrapper implements ObjectWrapper {private final Collection<Object> object;public CollectionWrapper(MetaObject metaObject, Collection<Object> object) {this.object = object;}@Overridepublic Object get(PropertyTokenizer prop) {throw new UnsupportedOperationException();}@Overridepublic void set(PropertyTokenizer prop, Object value) {throw new UnsupportedOperationException();}@Overridepublic String findProperty(String name, boolean useCamelCaseMapping) {throw new UnsupportedOperationException();}@Overridepublic String[] getGetterNames() {throw new UnsupportedOperationException();}@Overridepublic String[] getSetterNames() {throw new UnsupportedOperationException();}@Overridepublic Class<?> getSetterType(String name) {throw new UnsupportedOperationException();}@Overridepublic Class<?> getGetterType(String name) {throw new UnsupportedOperationException();}@Overridepublic boolean hasSetter(String name) {throw new UnsupportedOperationException();}@Overridepublic boolean hasGetter(String name) {throw new UnsupportedOperationException();}@Overridepublic MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {throw new UnsupportedOperationException();}@Overridepublic boolean isCollection() {return true;}@Overridepublic void add(Object element) {object.add(element);}@Overridepublic <E> void addAll(List<E> element) {object.addAll(element);}}
  • 仅仅支持 #add(Object element) 和 #addAll(List<E> element) 两个操作方法。

9. ObjectWrapperFactory

org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory ,ObjectWrapper 工厂接口。代码如下:

// ObjectWrapperFactory.javapublic interface ObjectWrapperFactory {/*** 是否包装了指定对象** @param object 指定对象* @return 是否*/boolean hasWrapperFor(Object object);/*** 获得指定对象的 ObjectWrapper 对象** @param metaObject MetaObject 对象* @param object 指定对象* @return ObjectWrapper 对象*/ObjectWrapper getWrapperFor(MetaObject metaObject, Object object);}

9.1 DefaultObjectWrapperFactory

org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory ,实现 ObjectWrapperFactory 接口,默认 ObjectWrapperFactory 实现类。代码如下:

public class DefaultObjectWrapperFactory implements ObjectWrapperFactory {@Overridepublic boolean hasWrapperFor(Object object) {return false;}@Overridepublic ObjectWrapper getWrapperFor(MetaObject metaObject, Object object) {throw new ReflectionException("The DefaultObjectWrapperFactory should never be called to provide an ObjectWrapper.");}}
  • 诶?貌似是个空的实现类???实际上,默认情况下,我们是不使用 ObjectWrapperFactory 对象的。

10. MetaObject

org.apache.ibatis.reflection.MetaObject ,对象元数据,提供了对象的属性值的获得和设置等等方法。😈 可以理解成,对 BaseWrapper 操作的进一步增强

10.1 构造方法

// MetaObject.java/*** 原始 Object 对象*/
private final Object originalObject;
/*** 封装过的 Object 对象*/
private final ObjectWrapper objectWrapper;
private final ObjectFactory objectFactory;
private final ObjectWrapperFactory objectWrapperFactory;
private final ReflectorFactory reflectorFactory;private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {this.originalObject = object;this.objectFactory = objectFactory;this.objectWrapperFactory = objectWrapperFactory;this.reflectorFactory = reflectorFactory;// <1>if (object instanceof ObjectWrapper) {this.objectWrapper = (ObjectWrapper) object;} else if (objectWrapperFactory.hasWrapperFor(object)) { // <2>// 创建 ObjectWrapper 对象this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);} else if (object instanceof Map) {// 创建 MapWrapper 对象this.objectWrapper = new MapWrapper(this, (Map) object);} else if (object instanceof Collection) {// 创建 CollectionWrapper 对象this.objectWrapper = new CollectionWrapper(this, (Collection) object);} else {// 创建 BeanWrapper 对象this.objectWrapper = new BeanWrapper(this, object);}
}
  • <1> 处,会根据 object 类型的不同,创建对应的 ObjectWrapper 对象。
    • 其中,<2> 处,我们可以看到 ObjectWrapperFactory 的使用,因为默认情况下的 DefaultObjectWrapperFactory 未实现任何逻辑,所以这块逻辑相当于暂时不起作用。如果想要起作用,需要自定义 ObjectWrapperFactory 的实现类。

10.2 forObject

#forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) 静态方法,创建 MetaObject 对象。代码如下:

// MetaObject.java/*** 创建 MetaObject 对象** @param object 原始 Object 对象* @param objectFactory* @param objectWrapperFactory* @param reflectorFactory* @return MetaObject 对象*/
public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {if (object == null) {return SystemMetaObject.NULL_META_OBJECT;} else {return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);}
}
  • 如果 object 为的情况下,返回 SystemMetaObject.NULL_META_OBJECT 。

10.3 metaObjectForProperty

#metaObjectForProperty(String name) 方法,创建指定属性的 MetaObject 对象。代码如下:

// MetaObject.javapublic MetaObject metaObjectForProperty(String name) {// 获得属性值Object value = getValue(name);// 创建 MetaObject 对象return MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory);
}

10.4 getValue

#getValue(String name) 方法,获得指定属性的值。代码如下:

// MetaObject.javapublic Object getValue(String name) {// 创建 PropertyTokenizer 对象,对 name 分词PropertyTokenizer prop = new PropertyTokenizer(name);// 有子表达式if (prop.hasNext()) {// 创建 MetaObject 对象MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());// <2> 递归判断子表达式 children ,获取值if (metaValue == SystemMetaObject.NULL_META_OBJECT) {return null;} else {return metaValue.getValue(prop.getChildren());}// 无子表达式} else {// <1> 获取值return objectWrapper.get(prop);}
}
  • 大体逻辑上,就是不断对 name 分词,递归查找属性,直到 <1> 处,返回最终的结果。
  • 比较特殊的是,在 <2> 处,如果属性的值为 null 时,则直接返回 null ,因为值就是空的哈。

10.5 setValue

#setValue(String name, Object value) 方法,设置指定属性的指定值。代码如下:

// MetaObject.javapublic void setValue(String name, Object value) {// 创建 PropertyTokenizer 对象,对 name 分词PropertyTokenizer prop = new PropertyTokenizer(name);// 有子表达式if (prop.hasNext()) {// 创建 MetaObject 对象MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());// 递归判断子表达式 children ,设置值if (metaValue == SystemMetaObject.NULL_META_OBJECT) {if (value == null) {// don't instantiate child path if value is nullreturn;} else {// <1> 创建值metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);}}// 设置值metaValue.setValue(prop.getChildren(), value);// 无子表达式} else {// <1> 设置值objectWrapper.set(prop, value);}
}
  • 大体逻辑上,就是不断对 name 分词,递归查找属性,最终在 <1> 处,设置对应的值。
  • 比较特殊的是,在 <2> 处,如果属性的值为 null 时,调用 ObjectWrapper#instantiatePropertyValue(name, prop, objectFactory) 方法,创建当前 name 的 prop 属性的空对象,然后继续递归。下 MetaObjectTest#shouldGetAndSetNestedMapPairUsingArraySyntax() 这个单元测试方法。

10.6 isCollection

#isCollection() 方法,判断是否为集合。代码如下:

// MetaObject.javapublic boolean isCollection() {return objectWrapper.isCollection();
}public void add(Object element) {objectWrapper.add(element);
}public <E> void addAll(List<E> list) {objectWrapper.addAll(list);
}
  • 直接调用 objectWrapper 的对应的方法。

11. SystemMetaObject

org.apache.ibatis.reflection.SystemMetaObject ,系统级的 MetaObject 对象,主要提供了 ObjectFactory、ObjectWrapperFactory、空 MetaObject 的单例。代码如下:

// SystemMetaObject.javapublic final class SystemMetaObject {/*** ObjectFactory 的单例*/public static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();/*** ObjectWrapperFactory 的单例*/public static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();/*** 空对象的 MetaObject 对象单例*/public static final MetaObject NULL_META_OBJECT = MetaObject.forObject(NullObject.class, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());private SystemMetaObject() {// Prevent Instantiation of Static Class}private static class NullObject {}/*** 创建 MetaObject 对象** @param object 指定对象* @return MetaObject 对象*/public static MetaObject forObject(Object object) {return MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());}}
  • 核心就是 #forObject(Object object) 方法,创建指定对象的 MetaObject 对象。

12. ParamNameUtil

org.apache.ibatis.reflection.ParamNameUtil ,参数名工具类,获得构造方法、普通方法的参数列表。代码如下:

// ParamNameUtil.javapublic class ParamNameUtil {/*** 获得普通方法的参数列表** @param method 普通方法* @return 参数集合*/public static List<String> getParamNames(Method method) {return getParameterNames(method);}/*** 获得构造方法的参数列表** @param constructor 构造方法* @return 参数集合*/public static List<String> getParamNames(Constructor<?> constructor) {return getParameterNames(constructor);}private static List<String> getParameterNames(Executable executable) {final List<String> names = new ArrayList<>();// 获得 Parameter 数组final Parameter[] params = executable.getParameters();// 获得参数名,并添加到 names 中for (Parameter param : params) {names.add(param.getName());}return names;}private ParamNameUtil() {super();}}

13. ParamNameResolver

org.apache.ibatis.reflection.ParamNameResolver ,参数名解析器。

13.1 构造方法

// ParamNameResolver.java/*** <p>* The key is the index and the value is the name of the parameter.<br />* The name is obtained from {@link Param} if specified. When {@link Param} is not specified,* the parameter index is used. Note that this index could be different from the actual index* when the method has special parameters (i.e. {@link RowBounds} or {@link ResultHandler}).* </p>* <ul>* <li>aMethod(@Param("M") int a, @Param("N") int b) -&gt; {{0, "M"}, {1, "N"}}</li>* <li>aMethod(int a, int b) -&gt; {{0, "0"}, {1, "1"}}</li>* <li>aMethod(int a, RowBounds rb, int b) -&gt; {{0, "0"}, {2, "1"}}</li>* </ul>** 参数名映射** KEY:参数顺序* VALUE:参数名*/
private final SortedMap<Integer, String> names;
/*** 是否有 {@link Param} 注解的参数*/
private boolean hasParamAnnotation;public ParamNameResolver(Configuration config, Method method) {final Class<?>[] paramTypes = method.getParameterTypes();final Annotation[][] paramAnnotations = method.getParameterAnnotations();final SortedMap<Integer, String> map = new TreeMap<>();int paramCount = paramAnnotations.length;// get names from @Param annotationsfor (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {// 忽略,如果是特殊参数if (isSpecialParameter(paramTypes[paramIndex])) {// skip special parameterscontinue;}String name = null;// 首先,从 @Param 注解中获取参数for (Annotation annotation : paramAnnotations[paramIndex]) {if (annotation instanceof Param) {hasParamAnnotation = true;name = ((Param) annotation).value();break;}}if (name == null) {// @Param was not specified.// 其次,获取真实的参数名if (config.isUseActualParamName()) { // 默认开启name = getActualParamName(method, paramIndex);}// 最差,使用 map 的顺序,作为编号if (name == null) {// use the parameter index as the name ("0", "1", ...)// gcode issue #71name = String.valueOf(map.size());}}// 添加到 map 中map.put(paramIndex, name);}// 构建不可变集合names = Collections.unmodifiableSortedMap(map);
}private String getActualParamName(Method method, int paramIndex) {return ParamNameUtil.getParamNames(method).get(paramIndex);
}private static boolean isSpecialParameter(Class<?> clazz) {return RowBounds.class.isAssignableFrom(clazz) || ResultHandler.class.isAssignableFrom(clazz);
}

13.2 getNamedParams

#getNamedParams(Object[] args) 方法,获得参数名与值的映射。代码如下:

// ParamNameResolver.javaprivate static final String GENERIC_NAME_PREFIX = "param";/*** <p>* A single non-special parameter is returned without a name.* Multiple parameters are named using the naming rule.* In addition to the default names, this method also adds the generic names (param1, param2,* ...).* </p>** 获得参数名与值的映射*/
public Object getNamedParams(Object[] args) {final int paramCount = names.size();// 无参数,则返回 nullif (args == null || paramCount == 0) {return null;// 只有一个非注解的参数,直接返回首元素} else if (!hasParamAnnotation && paramCount == 1) {return args[names.firstKey()];} else {// 集合。// 组合 1 :KEY:参数名,VALUE:参数值// 组合 2 :KEY:GENERIC_NAME_PREFIX + 参数顺序,VALUE :参数值final Map<String, Object> param = new ParamMap<>();int i = 0;// 遍历 names 集合for (Map.Entry<Integer, String> entry : names.entrySet()) {// 组合 1 :添加到 param 中param.put(entry.getValue(), args[entry.getKey()]);// add generic param names (param1, param2, ...)// 组合 2 :添加到 param 中final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);// ensure not to overwrite parameter named with @Paramif (!names.containsValue(genericParamName)) {param.put(genericParamName, args[entry.getKey()]);}i++;}return param;}
}

14. TypeParameterResolver

org.apache.ibatis.reflection.TypeParameterResolver ,工具类,java.lang.reflect.Type 参数解析器。因为 Type 是相对冷门的知识,我表示也不会,所以推荐先阅读如下任一文章:

  • 贾博岩 《我眼中的 Java-Type 体系(1)》

14.1 暴露方法

TypeParameterResolver 暴露了三个 公用静态方法,分别用于解析 Field 类型、Method 返回类型、方法参数类型。代码如下:

// TypeParameterResolver.java/*** 解析属性类型** @return The field type as {@link Type}. If it has type parameters in the declaration,<br>*         they will be resolved to the actual runtime {@link Type}s.*/
public static Type resolveFieldType(Field field, Type srcType) {// 属性类型Type fieldType = field.getGenericType();// 定义的类Class<?> declaringClass = field.getDeclaringClass();// 解析类型return resolveType(fieldType, srcType, declaringClass);
}/*** 解析方法返回类型** @return The return type of the method as {@link Type}. If it has type parameters in the declaration,<br>*         they will be resolved to the actual runtime {@link Type}s.*/
public static Type resolveReturnType(Method method, Type srcType) {// 属性类型Type returnType = method.getGenericReturnType();// 定义的类Class<?> declaringClass = method.getDeclaringClass();// 解析类型return resolveType(returnType, srcType, declaringClass);
}/*** 解析方法参数的类型数组** @return The parameter types of the method as an array of {@link Type}s. If they have type parameters in the declaration,<br>*         they will be resolved to the actual runtime {@link Type}s.*/
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;
}
  • 大体逻辑都类似,最终都会调用 #resolveType(Type type, Type srcType, Class<?> declaringClass) 方法,解析类型。

14.2 resolveType

#resolveType(Type type, Type srcType, Class<?> declaringClass) 方法,解析 type 类型。代码如下:

// TypeParameterResolver.java/*** 解析类型** @param type 类型* @param srcType 来源类型* @param declaringClass 定义的类* @return 解析后的类型*/
private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {if (type instanceof TypeVariable) {return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);} else if (type instanceof ParameterizedType) {return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);} else if (type instanceof GenericArrayType) {return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);} else {return type;}
}
  • 根据 type 对应不同的 Type 类型,调用不同的方法,进行解析。

14.2.1 resolveParameterizedType

#resolveParameterizedType(ParameterizedType parameterizedType, Type srcType, Class<?> declaringClass) 方法,解析 ParameterizedType 类型。代码如下:

// TypeParameterResolver.java/*** 解析 ParameterizedType 类型** @param parameterizedType ParameterizedType 类型* @param srcType 来源类型* @param declaringClass 定义的类* @return 解析后的类型*/
private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType, Class<?> declaringClass) {Class<?> rawType = (Class<?>) parameterizedType.getRawType();// 【1】解析 <> 中实际类型Type[] typeArgs = parameterizedType.getActualTypeArguments();Type[] args = new Type[typeArgs.length];for (int i = 0; i < typeArgs.length; i++) {if (typeArgs[i] instanceof TypeVariable) {args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], srcType, declaringClass);} else if (typeArgs[i] instanceof ParameterizedType) {args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], srcType, declaringClass);} else if (typeArgs[i] instanceof WildcardType) {args[i] = resolveWildcardType((WildcardType) typeArgs[i], srcType, declaringClass);} else {args[i] = typeArgs[i];}}// 【2】return new ParameterizedTypeImpl(rawType, null, args);
}
  • 【1】 处,解析 <> 中实际类型。
  • 【2】 处,创建 ParameterizedTypeImpl 对象。代码如下:

    // TypeParameterResolver.java 内部静态类/*** ParameterizedType 实现类** 参数化类型,即泛型。例如:List<T>、Map<K, V>等带有参数化的配置*/
    static class ParameterizedTypeImpl implements ParameterizedType {// 以 List<T> 举例子/*** <> 前面实际类型** 例如:List*/private Class<?> rawType;/*** 如果这个类型是某个属性所有,则获取这个所有者类型;否则,返回 null*/private Type ownerType;/*** <> 中实际类型** 例如:T*/private Type[] actualTypeArguments;public ParameterizedTypeImpl(Class<?> rawType, Type ownerType, Type[] actualTypeArguments) {super();this.rawType = rawType;this.ownerType = ownerType;this.actualTypeArguments = actualTypeArguments;}@Overridepublic Type[] getActualTypeArguments() {return actualTypeArguments;}@Overridepublic Type getOwnerType() {return ownerType;}@Overridepublic Type getRawType() {return rawType;}@Overridepublic String toString() {return "ParameterizedTypeImpl [rawType=" + rawType + ", ownerType=" + ownerType + ", actualTypeArguments=" + Arrays.toString(actualTypeArguments) + "]";}}
    

14.2.2 resolveWildcardType

#resolveWildcardType(WildcardType wildcardType, Type srcType, Class<?> declaringClass) 方法,解析 WildcardType 类型。代码如下:

// TypeParameterResolver.javaprivate static Type resolveWildcardType(WildcardType wildcardType, Type srcType, Class<?> declaringClass) {// <1.1> 解析泛型表达式下界(下限 super)Type[] lowerBounds = resolveWildcardTypeBounds(wildcardType.getLowerBounds(), srcType, declaringClass);// <1.2> 解析泛型表达式上界(上限 extends)Type[] upperBounds = resolveWildcardTypeBounds(wildcardType.getUpperBounds(), srcType, declaringClass);// <2> 创建 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.1><1.2> 处,解析泛型表达式下界(下限 super)和上界( 上限 extends )。
  • <2> 创建 WildcardTypeImpl 对象。代码如下:

    // TypeParameterResolver.java 内部静态类/*** WildcardType 实现类** 泛型表达式(或者通配符表达式),即 ? extend Number、? super Integer 这样的表达式。* WildcardType 虽然是 Type 的子接口,但却不是 Java 类型中的一种。*/
    static class WildcardTypeImpl implements WildcardType {/*** 泛型表达式下界(下限 super)*/private Type[] lowerBounds;/*** 泛型表达式上界(上界 extends)*/private Type[] upperBounds;WildcardTypeImpl(Type[] lowerBounds, Type[] upperBounds) {super();this.lowerBounds = lowerBounds;this.upperBounds = upperBounds;}@Overridepublic Type[] getLowerBounds() {return lowerBounds;}@Overridepublic Type[] getUpperBounds() {return upperBounds;}
    }static class GenericArrayTypeImpl implements GenericArrayType {private Type genericComponentType;GenericArrayTypeImpl(Type genericComponentType) {super();this.genericComponentType = genericComponentType;}@Overridepublic Type getGenericComponentType() {return genericComponentType;}
    }
    

14.2.3 resolveGenericArrayType

// TypeParameterResolver.javaprivate static Type resolveGenericArrayType(GenericArrayType genericArrayType, Type srcType, Class<?> declaringClass) {// 【1】解析 componentTypeType componentType = genericArrayType.getGenericComponentType();Type resolvedComponentType = null;if (componentType instanceof TypeVariable) {resolvedComponentType = resolveTypeVar((TypeVariable<?>) componentType, srcType, declaringClass);} else if (componentType instanceof GenericArrayType) {resolvedComponentType = resolveGenericArrayType((GenericArrayType) componentType, srcType, declaringClass);} else if (componentType instanceof ParameterizedType) {resolvedComponentType = resolveParameterizedType((ParameterizedType) componentType, srcType, declaringClass);}// 【2】创建 GenericArrayTypeImpl 对象if (resolvedComponentType instanceof Class) {return Array.newInstance((Class<?>) resolvedComponentType, 0).getClass();} else {return new GenericArrayTypeImpl(resolvedComponentType);}
}
  • 【1】 处,解析 componentType 类型。
  • 【2】 处,创建 GenericArrayTypeImpl 对象。代码如下:

    // TypeParameterResolver.java 内部静态类/*** GenericArrayType 实现类** 泛型数组类型,用来描述 ParameterizedType、TypeVariable 类型的数组;即 List<T>[]、T[] 等;*/
    static class GenericArrayTypeImpl implements GenericArrayType {/*** 数组元素类型*/private Type genericComponentType;GenericArrayTypeImpl(Type genericComponentType) {super();this.genericComponentType = genericComponentType;}@Overridepublic Type getGenericComponentType() {return genericComponentType;}}
    

14.2.4 resolveTypeVar

可以通过调试 org.apache.ibatis.reflection.TypeParameterResolverTest 这个单元测试类,触发各种情况。

15. ArrayUtil

org.apache.ibatis.reflection.ArrayUtil ,数组工具类。代码如下:

// ArrayUtil.javapublic class ArrayUtil {/*** Returns a hash code for {@code obj}.** @param obj*          The object to get a hash code for. May be an array or <code>null</code>.* @return A hash code of {@code obj} or 0 if {@code obj} is <code>null</code>*/public static int hashCode(Object obj) {if (obj == null) {// for consistency with Arrays#hashCode() and Objects#hashCode()return 0;}// 普通类final Class<?> clazz = obj.getClass();if (!clazz.isArray()) {return obj.hashCode();}// 数组类型final Class<?> componentType = clazz.getComponentType();if (long.class.equals(componentType)) {return Arrays.hashCode((long[]) obj);} else if (int.class.equals(componentType)) {return Arrays.hashCode((int[]) obj);} else if (short.class.equals(componentType)) {return Arrays.hashCode((short[]) obj);} else if (char.class.equals(componentType)) {return Arrays.hashCode((char[]) obj);} else if (byte.class.equals(componentType)) {return Arrays.hashCode((byte[]) obj);} else if (boolean.class.equals(componentType)) {return Arrays.hashCode((boolean[]) obj);} else if (float.class.equals(componentType)) {return Arrays.hashCode((float[]) obj);} else if (double.class.equals(componentType)) {return Arrays.hashCode((double[]) obj);} else {return Arrays.hashCode((Object[]) obj);}}/*** Compares two objects. Returns <code>true</code> if* <ul>* <li>{@code thisObj} and {@code thatObj} are both <code>null</code></li>* <li>{@code thisObj} and {@code thatObj} are instances of the same type and* {@link Object#equals(Object)} returns <code>true</code></li>* <li>{@code thisObj} and {@code thatObj} are arrays with the same component type and* equals() method of {@link Arrays} returns <code>true</code> (not deepEquals())</li>* </ul>** @param thisObj*          The left hand object to compare. May be an array or <code>null</code>* @param thatObj*          The right hand object to compare. May be an array or <code>null</code>* @return <code>true</code> if two objects are equal; <code>false</code> otherwise.*/public static boolean equals(Object thisObj, Object thatObj) {if (thisObj == null) {return thatObj == null;} else if (thatObj == null) {return false;}final Class<?> clazz = thisObj.getClass();if (!clazz.equals(thatObj.getClass())) {return false;}// 普通类if (!clazz.isArray()) {return thisObj.equals(thatObj);}// 数组类型final Class<?> componentType = clazz.getComponentType();if (long.class.equals(componentType)) {return Arrays.equals((long[]) thisObj, (long[]) thatObj);} else if (int.class.equals(componentType)) {return Arrays.equals((int[]) thisObj, (int[]) thatObj);} else if (short.class.equals(componentType)) {return Arrays.equals((short[]) thisObj, (short[]) thatObj);} else if (char.class.equals(componentType)) {return Arrays.equals((char[]) thisObj, (char[]) thatObj);} else if (byte.class.equals(componentType)) {return Arrays.equals((byte[]) thisObj, (byte[]) thatObj);} else if (boolean.class.equals(componentType)) {return Arrays.equals((boolean[]) thisObj, (boolean[]) thatObj);} else if (float.class.equals(componentType)) {return Arrays.equals((float[]) thisObj, (float[]) thatObj);} else if (double.class.equals(componentType)) {return Arrays.equals((double[]) thisObj, (double[]) thatObj);} else {return Arrays.equals((Object[]) thisObj, (Object[]) thatObj);}}/*** If the {@code obj} is an array, toString() method of {@link Arrays} is called. Otherwise* {@link Object#toString()} is called. Returns "null" if {@code obj} is <code>null</code>.** @param obj*          An object. May be an array or <code>null</code>.* @return String representation of the {@code obj}.*/public static String toString(Object obj) {if (obj == null) {return "null";}// 普通类final Class<?> clazz = obj.getClass();if (!clazz.isArray()) {return obj.toString();}// 数组类型final Class<?> componentType = obj.getClass().getComponentType();if (long.class.equals(componentType)) {return Arrays.toString((long[]) obj);} else if (int.class.equals(componentType)) {return Arrays.toString((int[]) obj);} else if (short.class.equals(componentType)) {return Arrays.toString((short[]) obj);} else if (char.class.equals(componentType)) {return Arrays.toString((char[]) obj);} else if (byte.class.equals(componentType)) {return Arrays.toString((byte[]) obj);} else if (boolean.class.equals(componentType)) {return Arrays.toString((boolean[]) obj);} else if (float.class.equals(componentType)) {return Arrays.toString((float[]) obj);} else if (double.class.equals(componentType)) {return Arrays.toString((double[]) obj);} else {return Arrays.toString((Object[]) obj);}}}

16. ExceptionUtil

org.apache.ibatis.reflection.ExceptionUtil ,异常工具类。代码如下:

// ExceptionUtil.javapublic class ExceptionUtil {private ExceptionUtil() {// Prevent Instantiation}/*** 去掉异常的包装** @param wrapped 被包装的异常* @return 去除包装后的异常*/public static Throwable unwrapThrowable(Throwable wrapped) {Throwable unwrapped = wrapped;while (true) {if (unwrapped instanceof InvocationTargetException) {unwrapped = ((InvocationTargetException) unwrapped).getTargetException();} else if (unwrapped instanceof UndeclaredThrowableException) {unwrapped = ((UndeclaredThrowableException) unwrapped).getUndeclaredThrowable();} else {return unwrapped;}}}}

总结

比想象中,长了超级超级超级多的文章,大家一定要仔细阅读哦。如果还是一脸懵X,那就多多调试哦!


Mybatis源码解析传送门:

MyBatis源码分析(一):搭建调试环境

MyBatis源码分析(二):项目结构

MyBatis源码分析(三):解析器模块

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/327294.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

16、Kubernetes核心技术 - 节点选择器、亲和和反亲和

目录 一、概述 二、节点名称 - nodeName 二、节点选择器 - nodeSelector 三、节点亲和性和反亲和性 3.1、亲和性和反亲和性 3.2、节点硬亲和性 3.3、节点软亲和性 3.4、节点反亲和性 3.5、注意点 四、Pod亲和性和反亲和性 4.1、亲和性和反亲和性 4.2、Pod亲和性/反…

【Java技术专题】「攻破技术盲区」攻破Java技术盲点之unsafe类的使用指南(打破Java的安全管控— sun.misc.unsafe)

Java后门机制 — sun.misc.unsafe 打破Java的安全管控关于Unsafe的编程建议实例化Unsafe后门对象使用sun.misc.Unsafe创建实例单例模式处理实现浅克隆&#xff08;直接获取内存的方式&#xff09;直接使用copyMemory原理分析 密码安全使用Unsafe类—示例代码 运行时动态创建类超…

lombok注解 @Data使用在继承类上时出现警告解决

一、警告问题 1、Data注解 Data 包含了 ToString、EqualsAndHashCode、Getter / Setter和RequiredArgsConstructor的功能。 当使用 Data注解时&#xff0c;则有了 EqualsAndHashCode注解&#xff08;即EqualsAndHashCode(callSuperfalse)&#xff09;&#xff0c;那么就会在此…

Transformer-MM-Explainability

two modalities are separated by the [SEP] token&#xff0c;the numbers in each attention module represent the Eq. number. E h _h h​ is the mean&#xff0c; ∇ \nabla ∇A : ∂ y t ∂ A {∂y_t}\over∂A ∂A∂yt​​for y t y_t yt​ which is the model’s out…

新手小白必了解c语言之字符串函数

本篇介绍字符串库函数为 目录 引言 一&#xff1a;字符串函数的头文件为#include 二&#xff1a;求字符串长度函数 &#xff08;strlen&#xff09; 1.函数介绍 2.函数使用举例 3.模拟实现 三&#xff1a;字符串复制函数(strcpy) 1.函数介绍 2.函数使用举例 3.模…

Java BIO、NIO、AIO、Netty知识详解(值得珍藏)

1. 什么是IO Java中I/O是以流为基础进行数据的输入输出的&#xff0c;所有数据被串行化(所谓串行化就是数据要按顺序进行输入输出)写入输出流。简单来说就是java通过io流方式和外部设备进行交互。 在Java类库中&#xff0c;IO部分的内容是很庞大的&#xff0c;因为它涉及的领…

计算机环境安全

操作系统安全----比如windows,linux 安全标识--实体唯一性 windows---主体&#xff1a;账户&#xff0c;计算机&#xff0c;服务 安全标识符SID-Security Identifier 普通用户SID是1000&#xff0c;管理用SID是500 linux---主体&#xff1a;用户&#xff0c;用户组&#xf…

Next.js 第一次接触

因为需要整个漂亮的在线文档&#xff0c;所以接触了next.js&#xff0c;因为对前端js本身不够熟悉&#xff0c;别说对react.js 又不会&#xff0c;时间又不允许深入研究&#xff0c;所以&#xff0c;为了加一个导航菜单&#xff0c;极其痛苦。 有点小bug&#xff0c;不过不影响…

体系化的进阶学习内容

UWA学堂&#xff1a;传播游戏行业的体系化的进阶学习内容。UWA学堂作为面向开发者的在线学习平台&#xff0c;目前已经上线272门课程&#xff0c;涵盖了3D引擎渲染、UI、逻辑代码等多个模块&#xff0c;拥有完整的学习体系&#xff0c;一直致力于为广大的开发者提供更丰富、更优…

云服务器安装mysql全流程

一、下载安装包 官网链接&#xff1a;MySQL :: Download MySQL Community Server 选择适合自己版本和操作系统 二、安装包上传服务器 在本地终端执行scp命令 三、服务器上使用安装包 卸载旧版本 #检查是否之前安装过mysql服务 [lighthouseVM-24-3-opencloudos software]# r…

3D人体姿态估计(教程+代码)

3D人体姿态估计是指通过计算机视觉和深度学习技术&#xff0c;从图像或视频中推断出人体的三维姿态信息。它是计算机视觉领域的一个重要研究方向&#xff0c;具有广泛的应用潜力&#xff0c;如人机交互、运动分析、虚拟现实、增强现实等。 传统的2D人体姿态估计方法主要关注通…

OpenHarmony应用构建工具Hvigor的构建流程

前言 OpenHarmony 应用和服务使用 Hvigor 作为工程的构建工具。本篇文章将介绍 Hvigor 的构建流程&#xff0c;通过修改脚本配置使 Hvigor 执行自定义任务。 Hvigor 的构建流程 加载命令行参数和环境变量&#xff1b;初始化项目结构&#xff0c;创建 Project 和 Module 实例…