Mybatis原码学习(三)Reflector

相对于java自带的反射功能,Mybatis封装了更适合本身的反射工具箱,提供了更简洁的API

Reflector

Reflector是Mybatis中反射模块的基础,每个Reflector对象都对应了一个类

下面是Reflector类中的各个字段:

//对应的class类型
  private Class<?> type;
  //对应的getter方法的属性
  private String[] readablePropertyNames = EMPTY_STRING_ARRAY;
  //对应的setter方法的属性
  private String[] writeablePropertyNames = EMPTY_STRING_ARRAY;
  //属性名称-》setter方法封装
  private Map<String, Invoker> setMethods = new HashMap<String, Invoker>();
  //属性名称—》getter方法封装
  private Map<String, Invoker> getMethods = new HashMap<String, Invoker>();
  //属性名称->setter方法返回值类型
  private Map<String, Class<?>> setTypes = new HashMap<String, Class<?>>();
  //属性名称->getter方法返回值类型
  private Map<String, Class<?>> getTypes = new HashMap<String, Class<?>>();
  //记录默认的构造方法
  private Constructor<?> defaultConstructor;
//属性名称大写->原有名称
  private Map<String, String> caseInsensitivePropertyMap = new HashMap<String, String>();

这里面就是后边的方法要填充的东西了,然后就在Reflector类的构造方法里面对这些字段进行处理。

public Reflector(Class<?> clazz) {
    type = clazz;//初始化type字段
    addDefaultConstructor(clazz);//构造方法处理
    addGetMethods(clazz);//填充getter映射
    addSetMethods(clazz);//填充setter映射
    addFields(clazz);//对没有getter/setter方法的处理
    readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]);//属性集合初始化
    writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]);//属性集合初始化
    for (String propName : readablePropertyNames) {//getter属性名称变大写,放入映射
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
    for (String propName : writeablePropertyNames) {//getter属性名称变大写,放入映射
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
  }

首先分析下addGetMethods方法(addSetMethods方法类似,不再说)
这个方法的作用上面注释也写了,是去填充getter属性名称——》getter方法的映射,主要是下面三个核心步骤:

  1. 调用Reflector.getClassMethods()方法,获取当前类和其所有父类的方法(包括接口方法),这个过程中会给所有方法生成一个唯一签名避免重复,然后返回一个methods类型的数组,这里面就装了该类所有的方法了。
  2. 然后按照JavaBean的定义,拿出步骤一中的所有方法集合中的getter方法,放到conflictingGetters集合中(HashMap<String,List>()类型),因为一个属性可能对于多个getter方法(比如父类中有,子类又实现了)。
  3. 最后就是对步骤二中的conflictingGetters进行筛选,对于每一个属性字段选出一个最合适的getter方法,然后调用addGetMethod()把信息填充到getMethods和getTypes字段里面(这两个就是最开始那里我们说要填充的,然后注意addGetMethod是没有s的,别看叉了)。

具体流程就是这样,代码我就不贴了,思路明白代码就很容易看了。

然后addFields就是处理没有getter和setter字段的属性。

还有之前提到的Invoker对象,其实是用的Invoker接口的一个实现类MethodInvoker,通过method字段封装了对应方法的Method对象。

ReflectorFactory

这个接口主要实现了对Reflector对象的创建和缓存:

public interface ReflectorFactory {
	//是否会缓存
  boolean isClassCacheEnabled();
	//设置是否缓存Reflector对象
  void setClassCacheEnabled(boolean classCacheEnabled);
	//创建指定class对应的Reflector对象
  Reflector findForClass(Class<?> type);
}

该接口的实现类DefaultReflectorFactory就是去干了上面接口提供的三个方法干的事,
主要就是判断用不用缓存,有没有缓存巴拉巴拉,我也不贴上来了,除了使用这个类,咱还可以在mybatis-config.xml中配置自定义实现类,从而实现功能上的拓展。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值