写点什么

聊聊 mybatis 的反射之 Reflector 类

作者:周杰伦本人
  • 2022-11-21
    山东
  • 本文字数:1931 字

    阅读完需:约 6 分钟

聊聊 mybatis 的反射之 Reflector 类

反射是一块重要的内容,java 中的反射让我们在程序运行的时候可以获取到 java 对象的属性和方法,mybatis 有自己的反射工具箱模块,下面我就简单说一下 mybatis 反射工具箱的一些类和方法


Reflector 类是反射器,通过给出的测试类 ReflectorTest 我们可以知道这个类的具体用法:


@Test  public void testGetSetterType() throws Exception {    Reflector reflector = Reflector.forClass(Section.class);    Assert.assertEquals(Long.class, reflector.getSetterType("id"));  }
复制代码


通过 Reflector 的构造器,我们也能知道,只需要传入 Class 对象,Reflector 就能解析这个 Class 对象,并把 Class 类的信息分类填充到 Reflector 类自定的一些成员变量中


private Reflector(Class<?> clazz) {    type = clazz;    //加入构造函数    addDefaultConstructor(clazz);    //加入getter    addGetMethods(clazz);    //加入setter    addSetMethods(clazz);    //加入字段    addFields(clazz);    readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]);    writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]);    for (String propName : readablePropertyNames) {        //这里为了能找到某一个属性,就把他变成大写作为map的key。。。      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);    }    for (String propName : writeablePropertyNames) {      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);    }  }
复制代码


  1. ,type 记录 class 的类型

  2. addDefaultConstructor 是通过反射得到 Class 的无参构造方法

  3. addGetMethods()方法就是用来读取 Class 的 getter 方法,然后放入 getMethods 集合中和 getTypes 集合中,

  4. addSetMethods()方法就是读取 Class 文件的 setter 方法,放入 setMethods 方法列表集合和 setTypes 类型列表集合中

  5. addFields()方法是针对 class 中没有 getter setter 方法的字段生成 GetFieldInvoker 类来放入 getMethods、getTypes、setMethods 和 setTypes 集合中

  6. 然后初始化 readablePropertyNames 和 writeablePropertyNames,readablePropertyNames 是 getter 的属性列表集合,writeablePropertyNames 是 setter 的属性列表集合

  7. 把 readablePropertyNames 和 writeablePropertyNames 中全部转为大写,保存到 caseInsensitivePropertyMap 中,key 是属性名的大写,value 是属性名


步骤三中我们提到 addGetMethods()方法就是用来读取 Class 的 getter 方法,然后放入 getMethods 集合中和 getTypes 集合中,具体是怎么做的呢?看一下源码:


private void addGetMethods(Class<?> cls) {    Map<String, List<Method>> conflictingGetters = new HashMap<String, List<Method>>();    //这里getter和setter都调用了getClassMethods,有点浪费效率了。不妨把addGetMethods,addSetMethods合并成一个方法叫addMethods    Method[] methods = getClassMethods(cls);    for (Method method : methods) {      String name = method.getName();      if (name.startsWith("get") && name.length() > 3) {        if (method.getParameterTypes().length == 0) {          name = PropertyNamer.methodToProperty(name);          addMethodConflict(conflictingGetters, name, method);        }      } else if (name.startsWith("is") && name.length() > 2) {        if (method.getParameterTypes().length == 0) {          name = PropertyNamer.methodToProperty(name);          addMethodConflict(conflictingGetters, name, method);        }      }    }    resolveGetterConflicts(conflictingGetters);  }
复制代码


  1. 调用 getClassMethods(cls);获取方法信息,点进去这个方法可以看到定义了一个 map 集合Map<String, Method> uniqueMethods = new HashMap<String, Method>(); 它的 key 是返回值类型 #方法名称:参数类型:参数类型。。。,value 是 Method 对象,key 保证全局唯一,使用 map 能进行去重

  2. 获取到这些 methods 对象后,循环遍历,找出 getter 方法来,放入 conflictingGetters 集合中,key 是属性名。value 是对应的 getter 方法的集合,为什么是集合呢,因为有可能存在方法的重写

  3. 最后 resolveGetterConflicts()方法解决签名的冲突,就是比较 getter 方法的返回值,取子类的 getter 方法,在这个方法里调用 addGetMethod 把对应的 Method 生成 MethodInvoker 对象保存到 getMethods 中

总结

今天主要介绍了一下 mybatis 反射模块的 Reflector 类的构造方法的一些细节和用到成员变量,希望 mybatis 源码的分析能对你有所帮助。

发布于: 刚刚阅读数: 3
用户头像

还未添加个人签名 2020-02-29 加入

公众号《周结论本人》,多平台优质博主

评论

发布
暂无评论
聊聊mybatis的反射之Reflector类_11月月更_周杰伦本人_InfoQ写作社区