Mybatis源码解析三——反射模块(Reflector)

反射模块(Reflector)

Mybatis源码解析一——搭建阅读环境
Mybatis源码解析二——解析器模块(parsing)
Mybatis源码解析三——反射模块(Reflector)


文章目录

  • 反射模块(Reflector)
  • 前言
  • 一、reflector包结构
  • 二、reflector测试类结构
  • 三、ReflectorFactory
    • 3.1DefaultReflectorFactory
  • 四、Reflector
    • 4.1Reflector构造器
      • 4.1.1addDefaultConstructor
      • 4.1.2addGetMethods
      • 4.1.3addSetMethods
      • 4.1.4addFields
  • 五、ReflectorTest
  • 六、Invoke
    • 6.1GetFieldInvoker
    • 6.2SetFieldInvoker
    • 6.3MethodInvoker
    • 6.4AmbiguousMethodInvoker


前言

Reflector(反射)模块提供了一系列的反射相关操作,封装了java反射相关的API,对外提供了更简单的调用方式。

一、reflector包结构

Mybatis源码解析三——反射模块(Reflector)_第1张图片

二、reflector测试类结构

Mybatis源码解析三——反射模块(Reflector)_第2张图片

三、ReflectorFactory

public interface ReflectorFactory {

  /**
   * 是否开启Reflector类缓存
   * @return
   */
  boolean isClassCacheEnabled();

  /**
   * 设置是否开启Reflector类缓存
   * @param classCacheEnabled
   */
  void setClassCacheEnabled(boolean classCacheEnabled);

  /**
   * 获取指定类的 Reflector
   * @param type
   * @return
   */
  Reflector findForClass(Class<?> type);
}

ReflectorFactory工厂,顾名思义,是用来创建Reflector对象的,定义了三个接口,很简单。
可以看到这个接口只有一个实现类DefaultReflectorFactory
Mybatis源码解析三——反射模块(Reflector)_第3张图片

3.1DefaultReflectorFactory

public class DefaultReflectorFactory implements ReflectorFactory {
  private boolean classCacheEnabled = true;
  private final ConcurrentMap<Class<?>, 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) {
    /**
     * 开启缓存
     *    则先从缓存中查询,没有则新建
     * 未开启缓存
     *    每次获取都是新建
     */
    if (classCacheEnabled) {
      // synchronized (type) removed see issue #461
      return reflectorMap.computeIfAbsent(type, Reflector::new);
    } else {
      return new Reflector(type);
    }
  }

}

可以看到,默认情况下,DefaultReflectorFactory是开启缓存的。最重要的是 findForClass 方法,开启缓存,就先查询缓存,没有则创建。关闭缓存,则每次调用都创建新的Reflector对象。
下面就看看Reflector这个核心对象。

四、Reflector

稍微会有些复杂,一点点来看,首先我们看看对象内部的属性有哪些

public class Reflector {

  /**
   * 对应的类
   */
  private final Class<?> type;
  /**
   * 可读属性数组
   */
  private final String[] readablePropertyNames;
  /**
   * 可写属性数组
   */
  private final String[] writablePropertyNames;
  /**
   * setting方法映射
   *
   * key: 属性名
   * value: 方法
   */
  private final Map<String, Invoker> setMethods = new HashMap<>();
  /**
   * getting方法映射
   */
  private final Map<String, Invoker> getMethods = new HashMap<>();
  /**
   * setting方法参数映射
   */
  private final Map<String, Class<?>> setTypes = new HashMap<>();
  /**
   * getting方法返回数据类型映射
   */
  private final Map<String, Class<?>> getTypes = new HashMap<>();
  /**
   * 默认构造方法
   */
  private Constructor<?> defaultConstructor;

  /**
   * 忽略大小写的属性集合
   */
  private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();
}

可以看出,Reflector对象目的就是把一个类的属性和其方法对应起来,组成map集合,以方便调用。

4.1Reflector构造器

在Reflector内部,提供了一个有参构造,这个构造器非常重要,并且代码量比较大。

public class Reflector {
  public Reflector(Class<?> clazz) {
    type = clazz;
    //设置默认构造器,就是获取无参构造
    addDefaultConstructor(clazz);
    //设置getting方法
    addGetMethods(clazz);
    //设置setting方法
    addSetMethods(clazz);
    //设置属性  有一些属性没有提供get或者set方法,所以在get、set方法设定的时候,会漏掉这些属性
    addFields(clazz);
    //设置可读属性
    readablePropertyNames = getMethods.keySet().toArray(new String[0]);
    //设置可写属性
    writablePropertyNames = setMethods.keySet().toArray(new String[0]);
    //设置不区分大小写的属性集合   可读属性+可写属性
    for (String propName : readablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
    for (String propName : writablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
  }
}

在构造器中,调用了一系列方法,完成了对上述的几个属性的初始化,底层调用的是java的反射相关方法,当然有MyBatis自己的处理,一个个来看。

4.1.1addDefaultConstructor

这个方法的作用是获取默认的构造器

  private void addDefaultConstructor(Class<?> clazz) {
    //获取当前clazz中声明的构造器
    Constructor<?>[] constructors = clazz.getDeclaredConstructors();
    //流式便利,过滤出参数列表长度为0的构造器,也就是无参构造,如果找到,就赋值给defaultConstructor属性
    Arrays.stream(constructors).filter(constructor -> constructor.getParameterTypes().length == 0)
      .findAny().ifPresent(constructor -> this.defaultConstructor = constructor);
  }

4.1.2addGetMethods

顾名思义,获得所有的get方法

private void addGetMethods(Class<?> clazz) {
    Map<String, List<Method>> conflictingGetters = new HashMap<>();
    //获取类的方法
    Method[] methods = getClassMethods(clazz);
    //流式便利方法,过滤出无参、且方法名为“get”或“is”开头 的方法,也就是getting方法
    Arrays.stream(methods).filter(m -> m.getParameterTypes().length == 0 && PropertyNamer.isGetter(m.getName()))
      // PropertyNamer.methodToProperty(m.getName())  根据方法名获取属性名
      //将getting方法放入映射,key为属性名,value为get方法集合
      .forEach(m -> addMethodConflict(conflictingGetters, PropertyNamer.methodToProperty(m.getName()), m));
    //解决getting方法冲突 最终一个属性只能保留一个对应的方法
    resolveGetterConflicts(conflictingGetters);
  }

getClassMethods

  private Method[] getClassMethods(Class<?> clazz) {
    //每个方法的签名与该方法的映射
    Map<String, Method> uniqueMethods = new HashMap<>();
    Class<?> currentClass = clazz;
    //循环类,类的父类,父类的父类,直到Object
    while (currentClass != null && currentClass != Object.class) {
      //将当前类中的方法增加在映射中
      addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());

      // we also need to look for interface methods -
      // because the class may be abstract
      Class<?>[] interfaces = currentClass.getInterfaces();
      for (Class<?> anInterface : interfaces) {
        addUniqueMethods(uniqueMethods, anInterface.getMethods());
      }

      //将当前类设置为其父类,达到遍历效果
      currentClass = currentClass.getSuperclass();
    }

    //将方法数组返回
    Collection<Method> methods = uniqueMethods.values();

    return methods.toArray(new Method[0]);
  }

这里是从子类到父类的一个循环,一直到Object类。

addUniqueMethods

  private void addUniqueMethods(Map<String, Method> uniqueMethods, Method[] methods) {
    //遍历方法
    for (Method currentMethod : methods) {
      //判断当前方法是否是桥接方法,忽略了桥接方法
      if (!currentMethod.isBridge()) {
        //获取方法签名
        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 中,就put
        if (!uniqueMethods.containsKey(signature)) {
          uniqueMethods.put(signature, currentMethod);
        }
      }
    }
  }

判断是否是桥接方法,是因为java的泛型是伪泛型,不清楚的可以看看java泛型擦除相关的知识。

至此,获得了当前类的所有方法,然后使用流式便利筛选出get方法,isGetter方法很简单,这里不贴了。
methodToProperty方法的作用就是根据方法名获取到属性名,很简单,略过。
addMethodConflict方法是生成Map conflictingMethods的。其中key是属性名,value是方法列表,这里注意,同一个属性,可能对应两个get方法。

  private void addMethodConflict(Map<String, List<Method>> conflictingMethods, String name, Method method) {
    //判读是否是有效的属性名
    if (isValidPropertyName(name)) {
      //获取key为当前属性名的方法集合,如果不存在或者为null,就返回一个新的集合
      //JDK8的写法,针不戳
      List<Method> list = conflictingMethods.computeIfAbsent(name, k -> new ArrayList<>());
      //将当前方法加入这个集合
      list.add(method);
    }
  }

conflictingMethods.computeIfAbsent(name, k -> new ArrayList<>()); java8的写法,还是很舒服的!

resolveGetterConflicts方法主要是解决冲突,因为之前得到的map中,属性key对应的get方法可能有多个,这里要选出最合适的get方法。

  private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
    //遍历获取到的Map集合
    //遍历每个属性,查找其最匹配的方法。因为子类可以覆写父类的方法,所以一个属性,可能对应多个 getting 方法
    for (Entry<String, List<Method>> entry : conflictingGetters.entrySet()) {
      Method winner = null;
      String propName = entry.getKey();
      //是否有歧义,模棱两可
      boolean isAmbiguous = false;
      //遍历当前属性对应的方法集合
      for (Method candidate : entry.getValue()) {
        //首次进入,winner为null,将第一个方法赋值给winner,如果集合中有多个方法,第二次进来winner就不再为null
        if (winner == null) {
          winner = candidate;
          continue;
        }
        //winner不等于null,获取了winner与当前候选人的返回值类型
        Class<?> winnerType = winner.getReturnType();
        Class<?> candidateType = candidate.getReturnType();
        //判断两者返回值类型是否相同
        if (candidateType.equals(winnerType)) {
          //判断返回是否是布尔类型
          //只有boolean类型的返回值允许有两个相同的方法
          if (!boolean.class.equals(candidateType)) {
            //返回值非boolean类型,设置为有歧义
            isAmbiguous = true;
            break;
          } else if (candidate.getName().startsWith("is")) {
            //boolean类型的返回值,以is开头的方法被认为是最合适的
            winner = candidate;
          }
          //candidateType 是 winnerType 的超类或者超接口 则winner是最合适的
        } else if (candidateType.isAssignableFrom(winnerType)) {
          // OK getter type is descendant
          //winnerType 是 candidateType 的超类或者超接口 则candidate是最合适的
        } else if (winnerType.isAssignableFrom(candidateType)) {
          winner = candidate;
        } else {
          //上述条件都没达成,说明有歧义
          isAmbiguous = true;
          break;
        }
      }
      /**
       * 将解决冲突后的getting方法加入,如果是有歧义的,那就生成歧义方法调用者
       */
      addGetMethod(propName, winner, isAmbiguous);
    }
  }

主要实现的就是在多个get方法中选择一个是当前类的get方法,如果返回值是boolean类型,则选择is开头的方法,因为这是符合规范的。若返回值类型非boolean类型,则选择类型小的那个方法,这是由java的继承决定的。但是,当返回值类型并非boolean类型,且两者返回值类型没有继承关系时,就无法选择出那个方法更适合,此时,只好生成一个歧义的方法调用者,具体实现在addGetMethod方法内部。

  private void addGetMethod(String name, Method method, boolean isAmbiguous) {
    //如果有歧义,就生成AmbiguousMethodInvoker(调用时会抛出自定义异常),否则生成正常方法
    MethodInvoker invoker = isAmbiguous
        ? new AmbiguousMethodInvoker(method, MessageFormat.format(
            "Illegal overloaded getter method with ambiguous type for property ''{0}'' in class ''{1}''. This breaks the JavaBeans specification and can cause unpredictable results.",
            name, method.getDeclaringClass().getName()))
        : new MethodInvoker(method);
    getMethods.put(name, invoker);
    //获取getting方法的返回数据类型
    Type returnType = TypeParameterResolver.resolveReturnType(method, type);
    //根据type获取真正的class
    getTypes.put(name, typeToClass(returnType));
  }

关于MethodInvoker后面会讲,可以看到它是实现Invoker接口的
Mybatis源码解析三——反射模块(Reflector)_第4张图片
AmbiguousMethodInvoker继承了MethodInvoker。
根据上述方法,可以知道,若找到了合适的方法,则生成MethodInvoker,否则生成AmbiguousMethodInvoker。而AmbiguousMethodInvoker类的invoke方法的调用会直接抛出异常。

public class AmbiguousMethodInvoker extends MethodInvoker {
  private final String exceptionMessage;

  /**
   * 歧义方法调用者的实现就是在父类实现上增加了异常的设置
   * @param method
   * @param exceptionMessage
   */
  public AmbiguousMethodInvoker(Method method, String exceptionMessage) {
    super(method);
    this.exceptionMessage = exceptionMessage;
  }

  @Override
  public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
    throw new ReflectionException(exceptionMessage);
  }
}

4.1.3addSetMethods

addSetMethods方法和addGetMethods中很多方法是公用的。

private void addSetMethods(Class<?> clazz) {
    Map<String, List<Method>> conflictingSetters = new HashMap<>();
    Method[] methods = getClassMethods(clazz);
    Arrays.stream(methods).filter(m -> m.getParameterTypes().length == 1 && PropertyNamer.isSetter(m.getName()))
      .forEach(m -> addMethodConflict(conflictingSetters, PropertyNamer.methodToProperty(m.getName()), m));
    resolveSetterConflicts(conflictingSetters);
  }

重点看一下解决冲突的resolveSetterConflicts方法,和set方法解决冲突的实现不太一样

  private void resolveSetterConflicts(Map<String, List<Method>> conflictingSetters) {
    for (Entry<String, List<Method>> entry : conflictingSetters.entrySet()) {
      String propName = entry.getKey();
      List<Method> setters = entry.getValue();
      //由getting方法返回的数据类型,来确定setting方法的参数类型
      Class<?> getterType = getTypes.get(propName);
      //如果getMethods中获取的Invoker是AmbiguousMethodInvoker子类,则说明当前get方法是有歧义的
      boolean isGetterAmbiguous = getMethods.get(propName) instanceof AmbiguousMethodInvoker;
      //默认setting方法是没有歧义的
      boolean isSetterAmbiguous = false;
      Method match = null;
      //遍历当前属性的setting方法
      for (Method setter : setters) {
        //如果当前属性的get方法没有歧义,并且set方法的第一个参数类型是等于get方法的返回的类型,说明当前set方法是最优的
        if (!isGetterAmbiguous && setter.getParameterTypes()[0].equals(getterType)) {
          // should be the best match
          match = setter;
          break;
        }
        /**
         * 如果当前的set方法没有歧义,则进行进一步的选择。
         * 如果当前的set方法已经有歧义,则不再进行选择。(反正比较完了之后都会生成歧义的调用方法,后续的选择已经没有必要)
         */
        if (!isSetterAmbiguous) {
          /**
           * 如果match、setter第一个参数类型没有任何关系,就会创建产生歧义的方法调用。
           * 对于歧义的方法调用,pickBetterSetter方法会在内部将值赋给setMethods、setTypes,然后返回null
           * 因此,如果match==null,就说明已经产生了歧义方法
           */
          match = pickBetterSetter(match, setter, propName);
          isSetterAmbiguous = match == null;
        }
      }
      /**
       * match == null 时,说明产生歧义方法,此时不需处理,因为pickBetterSetter方法已经处理了后续逻辑
       * 否则,说明并非歧义方法,而是经过选择得到了唯一的最优方法,则应该做后续处理
       */
      if (match != null) {
        addSetMethod(propName, match);
      }
    }
  }

与get方法不同,set方法大多返回void,而参数列表长度大多为1,并且参数类型和get方法的返回类型相同,所以此方法中也是依赖于get方法的返回值来寻找最合适的set方法。当然,如果之前没能找打合适的get方法,自然也没法找到合适的set方法。

在pickBetterSetter方法中,进行了进一步的比较。

  private Method pickBetterSetter(Method setter1, Method setter2, String property) {
    if (setter1 == null) {
      return setter2;
    }
    //获取到两个方法的第一个参数的类型
    Class<?> paramType1 = setter1.getParameterTypes()[0];
    Class<?> paramType2 = setter2.getParameterTypes()[0];
    //如果方法1的参数是方法二参数的超类或者超接口
    /**
     * 也就是选择类型给小的作为更合适的接口
     * 因为遍历是由子类向父类进行的
     */
    if (paramType1.isAssignableFrom(paramType2)) {
      //则方法二是更合适的方法
      return setter2;
      //反之,则认为方法一更合适
    } else if (paramType2.isAssignableFrom(paramType1)) {
      return setter1;
    }
    //如果两个参数在类型上毫不相关,即没有父子类关系,则创建有歧义的方法调用者
    MethodInvoker invoker = new AmbiguousMethodInvoker(setter1,
        MessageFormat.format(
            "Ambiguous setters defined for property ''{0}'' in class ''{1}'' with types ''{2}'' and ''{3}''.",
            property, setter2.getDeclaringClass().getName(), paramType1.getName(), paramType2.getName()));
    setMethods.put(property, invoker);
    Type[] paramTypes = TypeParameterResolver.resolveParamTypes(setter1, type);
    setTypes.put(property, typeToClass(paramTypes[0]));
    return null;
  }

在这个方法中,如果没有找到合适的方法,就会生成歧义方法调用者,并且内部已经处理了setMethods、setTypes,所以对外就返回null。如果找到就直接返回那个合适的方法。

4.1.4addFields

  private void addFields(Class<?> clazz) {
    //获取所有声明的属性
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
      //当前属性不存在 setMethods 中
      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();
        //当前属性是非final且非static,将当前field加入
        if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) {
          addSetField(field);
        }
      }
      //不存在getMethods中
      if (!getMethods.containsKey(field.getName())) {
        addGetField(field);
      }
    }
    //处理父类
    if (clazz.getSuperclass() != null) {
      //递归
      addFields(clazz.getSuperclass());
    }
  }
  private void addSetField(Field field) {
    //先判断当前属性名是否合法
    if (isValidPropertyName(field.getName())) {
      //因为当前属性是不提供set方法的,所以创建的实例是 SetFieldInvoker
      setMethods.put(field.getName(), new SetFieldInvoker(field));
      Type fieldType = TypeParameterResolver.resolveFieldType(field, type);
      setTypes.put(field.getName(), typeToClass(fieldType));
    }
  }
  private void addGetField(Field field) {
    if (isValidPropertyName(field.getName())) {
      getMethods.put(field.getName(), new GetFieldInvoker(field));
      Type fieldType = TypeParameterResolver.resolveFieldType(field, type);
      getTypes.put(field.getName(), typeToClass(fieldType));
    }
  }

注意,两个方法创建的Invoker对象不一样。

五、ReflectorTest

测试类中根据用到的不同类对象,分为几个部分,建议每个部分都进行debug,尤其是关注什么情况下会产生歧义的方法。这里贴一个测试方法。

@Slf4j
class ReflectorTest {

  @Test
  void shouldSettersWithUnrelatedArgTypesThrowException() throws Exception {
    /**
     * setProp2三个方法会产生歧义
     */
    @SuppressWarnings("unused")
    class BeanClass {
      public void setProp1(String arg) {}
      public void setProp2(String arg) {}
      public void setProp2(Integer arg) {}
      public void setProp2(boolean arg) {}
    }
    ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
    Reflector reflector = reflectorFactory.findForClass(BeanClass.class);

    List<String> setableProps = Arrays.asList(reflector.getSetablePropertyNames());
    assertTrue(setableProps.contains("prop1"));
    assertTrue(setableProps.contains("prop2"));
    assertEquals("prop1", reflector.findPropertyName("PROP1"));
    assertEquals("prop2", reflector.findPropertyName("PROP2"));

    assertEquals(String.class, reflector.getSetterType("prop1"));
    assertNotNull(reflector.getSetInvoker("prop1"));

    Class<?> paramType = reflector.getSetterType("prop2");
    assertTrue(String.class.equals(paramType) || Integer.class.equals(paramType) || boolean.class.equals(paramType));

    //这里,因为prop2属性有三个set方法,并且三个set方法的第一个参数类型都不相同,且没有子父类关系,所以生成了歧义方法
    Invoker ambiguousInvoker = reflector.getSetInvoker("prop2");
    //因为是歧义方法,这里构建参数时做了判断
    Object[] param = String.class.equals(paramType)? new String[]{"x"} : new Integer[]{1};
    /**
     * 直接调用,不捕获异常,让异常直接抛出
     * {@link AmbiguousMethodInvoker#invoke(java.lang.Object, java.lang.Object[])}
     * 歧义方法的invoke直接将异常抛出
     */
    ambiguousInvoker.invoke(new BeanClass(), param);

    /**
     * junit的处理异常方式,写法蛮有意思的,可以参考下面这篇文章
     * https://blog.csdn.net/dnc8371/article/details/107267815?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522160921991016780257451000%252522%25252C%252522scm%252522%25253A%25252220140713.130102334.pc%25255Fall.%252522%25257D&request_id=160921991016780257451000&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-1-107267815.pc_search_result_no_baidu_js&utm_term=com.googlecode.catchexception.apis.BDDCatchException#when
     */
    when(() -> ambiguousInvoker.invoke(new BeanClass(), param));
    then(caughtException()).isInstanceOf(ReflectionException.class)
        .hasMessageMatching(
            "Ambiguous setters defined for property 'prop2' in class '" + BeanClass.class.getName().replace("$", "\\$")
                + "' with types '(java.lang.String|java.lang.Integer|boolean)' and '(java.lang.String|java.lang.Integer|boolean)'\\.");
  }
}

六、Invoke

Mybatis源码解析三——反射模块(Reflector)_第5张图片

6.1GetFieldInvoker

public class GetFieldInvoker implements Invoker {
  private final Field field;

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

  @Override
  public Object invoke(Object target, Object[] args) throws IllegalAccessException {
    try {
      return field.get(target);
    } catch (IllegalAccessException e) {
      if (Reflector.canControlMemberAccessible()) {
        field.setAccessible(true);
        return field.get(target);
      } else {
        throw e;
      }
    }
  }

  @Override
  public Class<?> getType() {
    return field.getType();
  }
}

6.2SetFieldInvoker

public class SetFieldInvoker implements Invoker {
  private final Field field;

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

  @Override
  public Object invoke(Object target, Object[] args) throws IllegalAccessException {
    try {
      field.set(target, args[0]);
    } catch (IllegalAccessException e) {
      if (Reflector.canControlMemberAccessible()) {
        field.setAccessible(true);
        field.set(target, args[0]);
      } else {
        throw e;
      }
    }
    return null;
  }

  @Override
  public Class<?> getType() {
    return field.getType();
  }
}

6.3MethodInvoker

/**
 * 创建MethodInvoker,说明当前方法没有歧义
 * @author Clinton Begin
 */
public class MethodInvoker implements Invoker {

  private final Class<?> type;
  private final Method method;


  public MethodInvoker(Method method) {
    this.method = method;
    //如果只有1个参数,说明是set方法,将参数1的类型返回
    if (method.getParameterTypes().length == 1) {
      type = method.getParameterTypes()[0];
      //否则,就将返回值类型返回
    } else {
      type = method.getReturnType();
    }
  }

  @Override
  public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
    try {
      return method.invoke(target, args);
    } catch (IllegalAccessException e) {
      if (Reflector.canControlMemberAccessible()) {
        method.setAccessible(true);
        return method.invoke(target, args);
      } else {
        throw e;
      }
    }
  }

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

6.4AmbiguousMethodInvoker

public class AmbiguousMethodInvoker extends MethodInvoker {
  private final String exceptionMessage;

  /**
   * 歧义方法调用者的实现就是在父类实现上增加了异常的设置
   * @param method
   * @param exceptionMessage
   */
  public AmbiguousMethodInvoker(Method method, String exceptionMessage) {
    super(method);
    this.exceptionMessage = exceptionMessage;
  }

  /**
   * 调用时直接抛出预设的异常
   * @param target
   * @param args
   * @return
   * @throws IllegalAccessException
   * @throws InvocationTargetException
   */
  @Override
  public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
    throw new ReflectionException(exceptionMessage);
  }
}

你可能感兴趣的:(Mybatis源码探究)