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

前言

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

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

对应 reflection 包。如下图所示:

MyBatis 源码分析(四):反射模块_第1张图片

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

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

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

2. Reflector

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

// Reflector.java

public class Reflector {

    /**
     * 对应的类
     */
    private final Class type;
    /**
     * 可读属性数组
     */
    private final String[] readablePropertyNames;
    /**
     * 可写属性集合
     */
    private final String[] writeablePropertyNames;
    /**
     * 属性对应的 setting 方法的映射。
     *
     * key 为属性名称
     * value 为 Invoker 对象
     */
    private final Map setMethods = new HashMap<>();
    /**
     * 属性对应的 getting 方法的映射。
     *
     * key 为属性名称
     * value 为 Invoker 对象
     */
    private final Map getMethods = new HashMap<>();
    /**
     * 属性对应的 setting 方法的方法参数类型的映射。{@link #setMethods}
     *
     * key 为属性名称
     * value 为方法参数类型
     */
    private final Map> setTypes = new HashMap<>();
    /**
     * 属性对应的 getting 方法的返回值类型的映射。{@link #getMethods}
     *
     * key 为属性名称
     * value 为返回值的类型
     */
    private final Map> getTypes = new HashMap<>();
    /**
     * 默认构造方法
     */
    private Constructor defaultConstructor;
    /**
     * 不区分大小写的属性集合
     */
    private Map caseInsensitivePropertyMap = new HashMap<>();

    public Reflector(Class clazz) {
        // 设置对应的类
        type = clazz;
        // <1> 初始化 defaultConstructor
        addDefaultConstructor(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.java

private 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.
                }
            }
            // 如果构造方法可以访问,赋值给 defaultConstructor
            if (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.java

private void addGetMethods(Class cls) {
    // <1> 属性与其 getting 方法的映射。
    Map> 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> conflictingMethods, String name, Method method) 方法,添加到 conflictingGetters 中。代码如下:

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

2.2.1 getClassMethods

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

// Reflector.java

private Method[] getClassMethods(Class cls) {
    // 每个方法签名与该方法的映射
    Map uniqueMethods = new HashMap<>();
    // 循环类,类的父类,类的父类的父类,直到父类为 Object
    Class 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 methods = uniqueMethods.values();
    return methods.toArray(new Method[methods.size()]);

  • <1> 和 <2> 处,会调用 #addUniqueMethods(Map uniqueMethods, Method[] methods) 方法,添加方法数组到 uniqueMethods 中。代码如下:

    // Reflector.java
    
    private void addUniqueMethods(Map 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.java
      
      private 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>) 方法,解决 getting 冲突方法。最终,一个属性,只保留一个对应的方法。代码如下:

// Reflector.java

private void resolveGetterConflicts(Map> conflictingGetters) {
    // 遍历每个属性,查找其最匹配的方法。因为子类可以覆写父类的方法,所以一个属性,可能对应多个 getting 方法
    for (Entry> 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 getXXXX();
    
    }
    
    public class B extends A {
    
        ArrayList getXXXX(); // 选择它
    
    }
    
  • <2> 处,调用 #addGetMethod(String name, Method method) 方法,添加方法到 getMethods 和 getTypes 中。代码如下:

    // Reflector.java
    
    private 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.java
      
      private 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.java
        
        private 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.java

private void addSetMethods(Class cls) {
    // 属性与其 setting 方法的映射。
    Map> conflictingSetters = new HashMap<>();
    // 获得所有方法
    Method[] methods = getClassMethods(cls);
    // 遍历所有方法
    for (Method method : methods) {
        String name = method.getName();
        // <1> 方法名为 set 开头
        // 参数数量为 1
        if (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> conflictingSetters) 方法,解决 setting 冲突方法。

2.3.1 resolveSetterConflicts

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

// Reflector.java

private void resolveSetterConflicts(Map> conflictingSetters) {
    // 遍历每个属性,查找其最匹配的方法。因为子类可以覆写父类的方法,所以一个属性,可能对应多个 setting 方法
    for (String propName : conflictingSetters.keySet()) {
        List 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 match
                match = 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.java
    
    private 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.java
    
    private 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.java

private 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 classloader
                int 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.java
    
    private 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.java
    
    private 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.java

public 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.java

public 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.java

public class DefaultReflectorFactory implements ReflectorFactory {

    /**
     * 是否缓存
     */
    private boolean classCacheEnabled = true;
    /**
     * Reflector 的缓存映射
     *
     * KEY:类
     * VALUE:Reflector 对象
     */
    private final ConcurrentMap, Reflector> reflectorMap = new ConcurrentHashMap<>();

    public DefaultReflectorFactory() {
    }

    @Override
    public boolean isClassCacheEnabled() {
        return classCacheEnabled;
    }

    @Override
    public void setClassCacheEnabled(boolean classCacheEnabled) {
        this.classCacheEnabled = classCacheEnabled;
    }

    @Override
    public Reflector findForClass(Class type) {
        // 开启缓存,则从 reflectorMap 中获取
        if (classCacheEnabled) {
            // synchronized (type) removed see issue #461
            return reflectorMap.computeIfAbsent(type, Reflector::new); // 不存在,则进行创建
        // 关闭缓存,则创建 Reflector 对象
        } else {
            return new Reflector(type);
        }
    }

}

4. Invoker

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

// Invoker.java

public 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.java

public class GetFieldInvoker implements Invoker {

    /**
     * Field 对象
     */
    private final Field field;

    public GetFieldInvoker(Field field) {
        this.field = field;
    }

    // 获得属性
    @Override
    public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
        return field.get(target);
    }

    // 返回属性类型
    @Override
    public Class getType() {
        return field.getType();
    }

}

4.2 SetFieldInvoker

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

// SetFieldInvoker.java

public class SetFieldInvoker implements Invoker {

    /**
     * Field 对象
     */
    private final Field field;

    public SetFieldInvoker(Field field) {
        this.field = field;
    }

    // 设置 Field 属性
    @Override
    public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
        field.set(target, args[0]);
        return null;
    }

    // 返回属性类型
    @Override
    public Class getType() {
        return field.getType();
    }

}

4.3 MethodInvoker

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

// MethodInvoker.java

public 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();
        }
    }

    // 执行指定方法
    @Override
    public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
        return method.invoke(target, args);
    }

    @Override
    public Class getType() {
        return type;
    }

}

5. ObjectFactory

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

// ObjectFactory.java

public 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 create(Class 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 create(Class type, List> constructorArgTypes, List 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
   */
   boolean isCollection(Class type);

}
 
  • 比较简单,一共有三类方法。

5.1 DefaultObjectFactory

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

5.1.1 create

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

// DefaultObjectFactory.java

@Override
public  T create(Class type) {
    return create(type, null, null);
}

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

    // DefaultObjectFactory.java
    
    protected 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 Support
            classToCreate = TreeSet.class;
        } else if (type == Set.class) {
            classToCreate = HashSet.class;
        } else {
            classToCreate = type;
        }
        return classToCreate;
    }
    
    • 对于我们常用的集合接口,返回对应的实现类。
  • <1> 处,调用 #instantiateClass(Class type, List> constructorArgTypes, List constructorArgs) 方法,创建指定类的对象。代码如下:

    // DefaultObjectFactory.java
    
    private  T instantiateClass(Class type, List> constructorArgTypes, List constructorArgs) {
        try {
            Constructor constructor;
            //  通过无参构造方法,创建指定类的对象
            if (constructorArgTypes == null || constructorArgs == null) {
                constructor = type.getDeclaredConstructor();
                if (!constructor.isAccessible()) {
                    constructor.setAccessible(true);
                }
                return constructor.newInstance();
            }
            //  使用特定构造方法,创建指定类的对象
            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) {
            // 拼接 argTypes
            StringBuilder 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 ,
            }
            // 拼接 argValues
            StringBuilder 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);
        }
    }
     
    • 代码比较简单,分成  两种情况。

    5.1.2 isCollection

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

    // DefaultObjectFactory.java
    
    @Override
    public  boolean isCollection(Class 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.java
    
    public 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> 记录当前 name
        indexedName = 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.java
    
    public String getChildren() {
        return children;
    }
    

    6.3.4 其它方法

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

    7. MetaClass

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

    7.1 构造方法

    // MetaClass.java
    
    private 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.java
      
      public static MetaClass forClass(Class type, ReflectorFactory reflectorFactory) {
          return new MetaClass(type, reflectorFactory);
      }
      
    • ② #metaClassForProperty(String name) 方法,创建类的指定属性的类的 MetaClass 对象。代码如下:

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

    7.2 findProperty

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

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

      // MetaClass.java
      
      public 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.java
    
    private 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 caseInsensitivePropertyMap = new HashMap<>();
    
    public String findPropertyName(String name) {
        return caseInsensitivePropertyMap.get(name.toUpperCase(Locale.ENGLISH));
    }
    

    7.3 hasGetter

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

    // MetaClass.java
    
    public 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.java
      
      private 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 是什么类型,这样才好通过该类型,继续获得 field
          if (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 ,至多一个。
                      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.java
    
    public 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.java
    
    public 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);
    
        /**
         * 添加多个元素到集合
         */
         void addAll(List element);
    
    }
    
    • 从接口中,我们可以看到,主要是对 MetaObject 方法的调用。

    ObjectWrapper 的子类实现如下图:

    MyBatis 源码分析(四):反射模块_第2张图片

    ObjectWrapper 类图

    8.1 BaseWrapper

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

    // BaseWrapper.java
    
    public 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.java
      
      private 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 list) 方法都是不支持的,直接抛出 UnsupportedOperationException 异常。代码如下:

    // BeanWrapper.java
    
    @Override
    public void add(Object element) {
        throw new UnsupportedOperationException();
    }
    
    @Override
    public  void addAll(List 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 map;
    
    // 属性的操作变成了
    map.put(prop.getName(), value);
    map.get(prop.getName());
    

    8.2 CollectionWrapper

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

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

    9. ObjectWrapperFactory

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

    // ObjectWrapperFactory.java
    
    public 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 {
    
        @Override
        public boolean hasWrapperFor(Object object) {
            return false;
        }
    
        @Override
        public 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.java
    
    public MetaObject metaObjectForProperty(String name) {
        // 获得属性值
        Object value = getValue(name);
        // 创建 MetaObject 对象
        return MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory);
    }
    

    10.4 getValue

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

    // MetaObject.java
    
    public 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.java
    
    public 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 null
                    return;
                } 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.java
    
    public boolean isCollection() {
        return objectWrapper.isCollection();
    }
    
    public void add(Object element) {
        objectWrapper.add(element);
    }
    
    public  void addAll(List list) {
        objectWrapper.addAll(list);
    }
    
    • 直接调用 objectWrapper 的对应的方法。

    11. SystemMetaObject

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

    // SystemMetaObject.java
    
    public 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.java
    
    public class ParamNameUtil {
    
        /**
         * 获得普通方法的参数列表
         *
         * @param method 普通方法
         * @return 参数集合
         */
        public static List getParamNames(Method method) {
            return getParameterNames(method);
        }
    
        /**
         * 获得构造方法的参数列表
         *
         * @param constructor 构造方法
         * @return 参数集合
         */
        public static List getParamNames(Constructor constructor) {
            return getParameterNames(constructor);
        }
    
        private static List getParameterNames(Executable executable) {
            final List 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
    
    /**
     * 

    * The key is the index and the value is the name of the parameter.
    * 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}). *

    *
      *
    • aMethod(@Param("M") int a, @Param("N") int b) -> {{0, "M"}, {1, "N"}}
    • *
    • aMethod(int a, int b) -> {{0, "0"}, {1, "1"}}
    • *
    • aMethod(int a, RowBounds rb, int b) -> {{0, "0"}, {2, "1"}}
    • *
    * * 参数名映射 * * KEY:参数顺序 * VALUE:参数名 */ private final SortedMap names; /** * 是否有 {@link Param} 注解的参数 */ private boolean hasParamAnnotation; public ParamNameResolver(Configuration config, Method method) { final Class[] paramTypes = method.getParameterTypes(); final Annotation[][] paramAnnotations = method.getParameterAnnotations(); final SortedMap map = new TreeMap<>(); int paramCount = paramAnnotations.length; // get names from @Param annotations for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) { // 忽略,如果是特殊参数 if (isSpecialParameter(paramTypes[paramIndex])) { // skip special parameters continue; } 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 #71 name = 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.java
    
    private static final String GENERIC_NAME_PREFIX = "param";
    
    /**
     * 

    * 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, * ...). *

    * * 获得参数名与值的映射 */ public Object getNamedParams(Object[] args) { final int paramCount = names.size(); // 无参数,则返回 null if (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 param = new ParamMap<>(); int i = 0; // 遍历 names 集合 for (Map.Entry 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 @Param if (!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,
    * 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,
    * 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,
    * 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、Map等带有参数化的配置
       */
      static class ParameterizedTypeImpl implements ParameterizedType {
      
          // 以 List 举例子
      
          /**
           * <> 前面实际类型
           *
           * 例如: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;
          }
      
          @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) + "]";
          }
      
      }
      

    14.2.2 resolveWildcardType

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

    // TypeParameterResolver.java
    
    private 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;
          }
      
          @Override
          public Type[] getLowerBounds() {
              return lowerBounds;
          }
      
          @Override
          public Type[] getUpperBounds() {
              return upperBounds;
          }
      }
      
      static class GenericArrayTypeImpl implements GenericArrayType {
          private Type genericComponentType;
      
          GenericArrayTypeImpl(Type genericComponentType) {
              super();
              this.genericComponentType = genericComponentType;
          }
      
          @Override
          public Type getGenericComponentType() {
              return genericComponentType;
          }
      }
      

    14.2.3 resolveGenericArrayType

    // TypeParameterResolver.java
    
    private static Type resolveGenericArrayType(GenericArrayType genericArrayType, Type srcType, Class declaringClass) {
        // 【1】解析 componentType
        Type 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[] 等;
       */
      static class GenericArrayTypeImpl implements GenericArrayType {
      
          /**
           * 数组元素类型
           */
          private Type genericComponentType;
      
          GenericArrayTypeImpl(Type genericComponentType) {
              super();
              this.genericComponentType = genericComponentType;
          }
      
          @Override
          public Type getGenericComponentType() {
              return genericComponentType;
          }
      
      }
      

    14.2.4 resolveTypeVar

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

    15. ArrayUtil

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

    // ArrayUtil.java
    
    public class ArrayUtil {
    
        /**
         * Returns a hash code for {@code obj}.
         *
         * @param obj
         *          The object to get a hash code for. May be an array or null.
         * @return A hash code of {@code obj} or 0 if {@code obj} is null
         */
        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 true if
         * 
      *
    • {@code thisObj} and {@code thatObj} are both null
    • *
    • {@code thisObj} and {@code thatObj} are instances of the same type and * {@link Object#equals(Object)} returns true
    • *
    • {@code thisObj} and {@code thatObj} are arrays with the same component type and * equals() method of {@link Arrays} returns true (not deepEquals())
    • *
    * * @param thisObj * The left hand object to compare. May be an array or null * @param thatObj * The right hand object to compare. May be an array or null * @return true if two objects are equal; false 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 null. * * @param obj * An object. May be an array or null. * @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.java
    
    public 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源码分析(三):解析器模块

    你可能感兴趣的:(源码解读,java,开发语言,mybatis)