聊聊mybatis的反射之Reflector类

举报
周杰伦本人 发表于 2022/07/27 14:46:12 2022/07/27
873 0 0
【摘要】 聊聊mybatis的反射之Invoker模块 MethodInvoker GetFieldInvoker ReflectorFactory 总结 聊聊mybatis的反射之Invoker模块上篇文章中我们介绍了mybatis的Reflector的构造方法,深入源码分析了一波,并了解到对于属性的getter setter方法封装成map集合中,key是属性名,value是MethodInvo...

聊聊mybatis的反射之Invoker模块

上篇文章中我们介绍了mybatis的Reflector的构造方法,深入源码分析了一波,并了解到对于属性的getter setter方法封装成map集合中,key是属性名,value是MethodInvoker,没有getter setter方法的属性也是封装到了map中,key是属性名,value是GetFieldInvoker和SetFieldInvoker,他们都是Invoker接口的实现类,下面看一下Invoker接口:

public interface Invoker {
  //调用
  Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;

  //取得类型
  Class<?> getType();
}

接口比较简单,只有两个方法:调用和获取类型,MethodInvoker, GetFieldInvoker ,SetFieldInvoker这三个类都实现了Invoker接口,MethodInvoker重写了invoke方法,方法中就是直接调用Method.invoke方法

MethodInvoker

public class MethodInvoker implements Invoker {

  private Class<?> type;
  private Method method;

  public MethodInvoker(Method method) {
    this.method = method;
    if (method.getParameterTypes().length == 1) {
      type = method.getParameterTypes()[0];
    } else {
      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;
  }
}

通过构造方法的逻辑,我们知道如果只有一个参数,返回参数类型,否则返回return的类型,在调用方法中直接调用了Method.invoke()方法

GetFieldInvoker

GetFieldInvoker是Field作为成员变量,invoke调用方法中直接调用field.get(target)方法,获取类型的时候也直接使用field.getType()方法来进行获取

public class GetFieldInvoker implements Invoker {
  private Field field;

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

  //就是调用Field.get
  @Override
  public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
    return field.get(target);
  }

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

对于其他的Invoker的接口这里不再一一分析了,整体逻辑都是很简单的。

ReflectorFactory

另外,ReflectorFactory 是一个工厂接口,它的默认实现类是DefaultReflectorFactory

接口:

public interface ReflectorFactory {

  boolean isClassCacheEnabled();

  void setClassCacheEnabled(boolean classCacheEnabled);

  Reflector findForClass(Class<?> type);
}

这里定义三个方法

而DefaultReflectorFactory实现类的代码如下:

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

  /**
   * 生产Reflector对象
   * @param type 目标类型
   * @return 目标类型的Reflector对象
   */
  @Override
  public Reflector findForClass(Class<?> type) {
    if (classCacheEnabled) { // 允许缓存
      // 生产入参type的反射器对象,并放入缓存
      return reflectorMap.computeIfAbsent(type, Reflector::new);
    } else {
      return new Reflector(type);
    }
  }

}

DefaultReflectorFactory中有一个ConcurrentHashMap成员变量,使用ConcurrentHashMap来做缓存,缓存的是class对应的Reflector对象信息,在允许进行缓存的情况下,会将入参type和对应的反射器对象放入到缓存中

总结

这篇文章主要讲解了Invoker接口和它实现类GetFieldInvoker,以及ReflectorFactory接口和它的默认实现类,Invoker接口主要是用来更加Class类来生成MethodInvoker, GetFieldInvoker ,SetFieldInvoker具体对象信息的并保存在map中供其他方法使用,ReflectorFactory是主要是用于Reflector对象的缓存,它的默认实现类是DefaultReflectorFactory,缓存是利用的ConcurrentHashMap来进行缓存的,希望看完这篇文章让你对Mybatis的反射模块有所帮助

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。