2.4.4.统一反射操作的适配器 Invoker

优质
小牛编辑
133浏览
2023-12-01
# Invoker

Invoker接口的作用是统一基于反射处理方法/属性的调用方式,他是适配器模式的一种实现。

适配器模式(包装模式)将一个类的接口适配成用户所期待的,是的原本由于接口不兼容而不能一起工作的类可以一起工作。

Invoker接口中定义了两个方法,invoke方法用于执行反射操作,获取响应的操作结果,getType方法用于获取方法或者属性对应的类型。

/**
 * mybatis中定义的用于执行方法或者属性反射操作的类
 * <p>
 * 作用是统一基于反射处理方法/属性的调用方式
 *
 * @author Clinton Begin
 */
public interface Invoker {
    /**
     * 执行反射操作
     *
     * @param target 方法或者属性执行的目标对象
     * @param args   方法或者属性执行时依赖的参数
     * @return 方法执行结果
     * @throws IllegalAccessException    无访问权限
     * @throws InvocationTargetException 反射执行异常
     */
    Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;

    /**
     * 方法或者属性对应的类型
     */
    Class<?> getType();
}

在mybatis中Invoker接口有三种实现形式:

GetFieldInvoker用于执行读取属性值的反射操作

GetFieldInvoker对象的构造方法需要传入一个Field属性:

  private final Field field;

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

他的invoke方法,基于java的反射实现了获取指定属性值的功能:

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

getType方法则返回对应的field属性的类型:

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

SetFieldInvoker用于执行设置属性值的反射操作

SetFieldInvoker对象的构造方法也需要传入一个Field属性:

  private final Field field;

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

他的invoke方法,基于java的反射实现了为指定属性设值的功能:

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

getType方法则返回对应的field属性的类型:

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

MethodInvoker用于执行方法的反射操作

他的构造方法需要一个Method类型的参数,在他的构造方法中,会根据方法有无入参判断方法是getter方法还是setter方法,如果是getter方法则获取方法的返回类型赋给type属性, 如果是setter方法则获取方法的入参类型赋给type属性:

  /**
   * 如果方法是getter方法,则表示返回值类型
   * 如果方法是setter方法,则表示入参类型
   */
  private final Class<?> type;
  /**
   * 方法本身
   */
  private final Method method;

  public MethodInvoker(Method method) {
      this.method = method;
      if (method.getParameterTypes().length == 1) {
          // 有方法入参,表示是setter方法
          type = method.getParameterTypes()[0];
      } else {
          // 无入参表示是getter方法
          type = method.getReturnType();
      }
  }

他的invoke方法,基于java的反射完成方法的调用:

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

getType方法则返回在构造方法中赋值的type属性的值:

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