Mybatis底层 Reflector信息解析者

问题:

        我在执行service层掉mapper层的时候会进到当前调用的实体类中的自定义方法,但是部分自定义方法是没有地方去调用过的,但是他还是会去调用。

这是我实体类中的自定义方法:

 public boolean isStr() {
        return true;
    }

    public boolean isSuperColumn(String javaField) {

}
    public boolean isSuperColumn() {

}

    public boolean isUsableColumn(String javaField) {
}

    public String readConverterExp() {
}

源码:

这里我下载的是若依的代码 Mybatis是3.5.9的源码,其他版本基本上不会有太大的区别。

在SqlSessionFactoryBean 的 Resource [] mapperlocations 属性中会保存扫描到的所有的**mapper.xml 文件的地址,并且会解析为一个 XMLMapperBuilder对象,并且获取namespace 并且解析 resultMap  中的属性 。

得到的是当前包下面的所有的实体类对应的信息,我这里包下面是两个实体类

通过反射获取:

之后循环中会执行到一下代码中,最终获取到的所有的方法都在 classMethods 中存放,

  public Reflector(Class<?> clazz) {
    type = clazz;
    // 默认的构造器
    addDefaultConstructor(clazz);
    // get方法
    addGetMethods(clazz);
    // set方法
    addSetMethods(clazz);
    // 属性字段
    addFields(clazz);
    // 从 getMethods 映射中获取可读属性名数组
    readablePropertyNames = getMethods.keySet().toArray(new String[0]);
    // 从 setMethods 映射中获取可写属性名数组
    writablePropertyNames = setMethods.keySet().toArray(new String[0]);
    // 将所有属性名的大写形式作为键,属性名作为值,存入到 caseInsensitivePropertyMap 中
    for (String propName : readablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
    for (String propName : writablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
  }

addGetMethods()、addSetMethods()、addDefaultConstructor()方法是过滤方法的关键:

 private void addDefaultConstructor(Class<?> clazz) {
    Constructor<?>[] constructors = clazz.getDeclaredConstructors();
// 判断有没有空参的构造器 有的话赋值给 defaultConstructor
    Arrays.stream(constructors).filter(constructor -> constructor.getParameterTypes().length == 0)
      .findAny().ifPresent(constructor -> this.defaultConstructor = constructor);
  }
private void addGetMethods(Method[] methods) {
Map<String, List<Method>> conflictingGetters = new HashMap<>();
//添加参数为空的
Arrays.stream(methods).filter(m -> m.getParameterTypes().length == 0 && PropertyNamer.isGetter(m.getName()))
.forEach(m -> addMethodConflict(conflictingGetters, PropertyNamer.methodToProperty(m.getName()), m));
resolveGetterConflicts(conflictingGetters);
}

再进入到isGetter方法:

public static boolean isGetter(String name) {
// 筛选出 get 或者 is 开头的
return (name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2);
}

真心大白!

结果:Mybatis会获取到service层调用mapper层接收的对象中的所有的方法并且进行过滤,以get开头或者 is 开头的 和参数为 空的 都会被获取到,并且后面的代码中也会循环使用到这些方法,所以才导致文章开头我贴上的代码我实际上没有调用但是一直在被调用。有不对的地方欢迎指正哈。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值