Mybatis源码之美:2.4.4.统一反射操作的适配器——Invoker

原创
2020/06/09 16:41
阅读数 177

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接口有三种实现形式:

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

关注我,一起学习更多知识

关注我</p>

展开阅读全文
打赏
0
0 收藏
分享
加载中
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部