美文网首页MyBatis源码剖析
[MyBatis源码分析 - 反射器模块 - 组件二] Invo

[MyBatis源码分析 - 反射器模块 - 组件二] Invo

作者: 小胡_鸭 | 来源:发表于2020-10-17 11:41 被阅读0次

一、简介

  Invoker 是一个接口,其实现类有 MethodInvokerSetFieldInvokerGetFieldInvoker,关系如下:


  Invoker 接口中定义了两个方法,分别用来执行反射调用和获取属性类型,源码如下:
public interface Invoker {
  /**
   * 执行调用
   * @param target  被反射调用的目标
   * @param args    参数
   * @return
   * @throws IllegalAccessException
   * @throws InvocationTargetException
   */
  Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;

  // 类
  Class<?> getType();
}

二、MethodInvoker

  对于有 getter/setter 方法的属性,使用的是 MethodInvoker 封装了 Method 对象,其 invoke() 方法是通过调用 Method.invoke() 方法实现的,获取属性类型时,通过判断方法是否带参数,分别获取参数类型和方法返回值作为属性类型,源码如下:

public class MethodInvoker implements Invoker {

  private Class<?> type;
  private Method method;

  public MethodInvoker(Method method) {
    this.method = method;

    // 获取属性类型,如果是setter方法,参数个数为1,属性类型为参数类型
    if (method.getParameterTypes().length == 1) {
      type = method.getParameterTypes()[0];
    } else {
      // 如果是getter方法,属性类型为方法的返回值
      type = method.getReturnType();
    }
  }

  // 通过调用Method.invoke()执行目标对象方法
  @Override
  public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
    return method.invoke(target, args);
  }

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

三、SetFieldInvoker & GetFieldInvoker

  没有 getter/setter 方法的属性,使用 GetFieldInvokerSetFieldInvoker 封装了属性对应的 Field 对象,通过调用 Field.get()/set() 实现获取设置属性值。

public class GetFieldInvoker implements Invoker {
  // 属性对应的Field对象
  private 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();
  }
}
public class SetFieldInvoker implements Invoker {
  // 属性对应的Field对象
  private Field field;

  public SetFieldInvoker(Field field) {
    this.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();
  }
}

四、总结

  对应 Reflector 对象来说,解析类元信息时,需要根据属性是否有对应的 getter/setter 方法来决定使用 Invoker 接口的哪个实现类,对于使用 Reflector 的代码来说,只需要知道其 getMethodssetMethods 集合中的值为 Invoker 对象,调用该对象可实现获取设置属性值即可。

相关文章

网友评论

    本文标题:[MyBatis源码分析 - 反射器模块 - 组件二] Invo

    本文链接:https://www.haomeiwen.com/subject/srpapktx.html