MyBatis 源码分析 - 配置文件解析过程 (4)

上面的描述比较简单,仅从上面的描述中,还不能让大家有更深入的理解。所以下面单独分析一下这几个类的逻辑,首先是ReflectorFactory。ReflectorFactory 是一个接口,MyBatis 中目前只有一个实现类DefaultReflectorFactory,它的分析如下:

2.3.2.1 DefaultReflectorFactory 源码分析

DefaultReflectorFactory 用于创建 Reflector,同时兼有缓存的功能,它的源码如下。

public class DefaultReflectorFactory implements ReflectorFactory { private boolean classCacheEnabled = true; /** 目标类和反射器映射缓存 */ private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap<Class<?>, Reflector>(); // 省略部分代码 @Override public Reflector findForClass(Class<?> type) { // classCacheEnabled 默认为 true if (classCacheEnabled) { // 从缓存中获取 Reflector 对象 Reflector cached = reflectorMap.get(type); // 缓存为空,则创建一个新的 Reflector 实例,并放入缓存中 if (cached == null) { cached = new Reflector(type); // 将 <type, cached> 映射缓存到 map 中,方便下次取用 reflectorMap.put(type, cached); } return cached; } else { // 创建一个新的 Reflector 实例 return new Reflector(type); } } }

如上,DefaultReflectorFactory 的findForClass方法逻辑不是很复杂,包含两个访存操作,和一个对象创建操作。代码注释的比较清楚了,就不多说了。接下来,来分析一下反射器 Reflector。

2.3.2.2 Reflector 源码分析

本小节,我们来看一下 Reflector 的源码。Reflector 这个类的用途主要是是通过反射获取目标类的 getter 方法及其返回值类型,setter 方法及其参数值类型等元信息。并将获取到的元信息缓存到相应的集合中,供后续使用。Reflector 本身代码比较多,这里不能一一分析。本小节,我将会分析三部分逻辑,分别如下:

Reflector 构造方法及成员变量分析

getter 方法解析过程

setter 方法解析过程

下面我们按照这个步骤进行分析,先来分析 Reflector 构造方法。

● Reflector 构造方法及成员变量分析

Reflector 构造方法中包含了很多初始化逻辑,目标类的元信息解析过程也是在构造方法中完成的,这些元信息最终会被保存到 Reflector 的成员变量中。下面我们先来看看 Reflector 的构造方法和相关的成员变量定义,代码如下:

public class Reflector { private final Class<?> type; private final String[] readablePropertyNames; private final String[] writeablePropertyNames; private final Map<String, Invoker> setMethods = new HashMap<String, Invoker>(); private final Map<String, Invoker> getMethods = new HashMap<String, Invoker>(); private final Map<String, Class<?>> setTypes = new HashMap<String, Class<?>>(); private final Map<String, Class<?>> getTypes = new HashMap<String, Class<?>>(); private Constructor<?> defaultConstructor; private Map<String, String> caseInsensitivePropertyMap = new HashMap<String, String>(); public Reflector(Class<?> clazz) { type = clazz; // 解析目标类的默认构造方法,并赋值给 defaultConstructor 变量 addDefaultConstructor(clazz); // 解析 getter 方法,并将解析结果放入 getMethods 中 addGetMethods(clazz); // 解析 setter 方法,并将解析结果放入 setMethods 中 addSetMethods(clazz); // 解析属性字段,并将解析结果添加到 setMethods 或 getMethods 中 addFields(clazz); // 从 getMethods 映射中获取可读属性名数组 readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]); // 从 setMethods 映射中获取可写属性名数组 writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]); // 将所有属性名的大写形式作为键,属性名作为值,存入到 caseInsensitivePropertyMap 中 for (String propName : readablePropertyNames) { caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); } for (String propName : writeablePropertyNames) { caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); } } // 省略其他方法 }

如上,Reflector 的构造方法看起来略为复杂,不过好在一些比较复杂的逻辑都封装在了相应的方法中,这样整体的逻辑就比较清晰了。Reflector 构造方法所做的事情均已进行了注释,大家对照着注释先看一下。相关方法的细节待会会进行分析。看完构造方法,下面我来通过表格的形式,列举一下 Reflector 部分成员变量的用途。如下:

变量名 类型 用途
readablePropertyNames   String[]   可读属性名称数组,用于保存 getter 方法对应的属性名称  
writeablePropertyNames   String[]   可写属性名称数组,用于保存 setter 方法对应的属性名称  
setMethods   Map<String, Invoker>    用于保存属性名称到 Invoke 的映射。setter 方法会被封装到 MethodInvoker 对象中,Invoke 实现类比较简单,大家自行分析  
getMethods   Map<String, Invoker>    用于保存属性名称到 Invoke 的映射。同上,getter 方法也会被封装到 MethodInvoker 对象中  
setTypes   Map<String, Class<?>>   用于保存 setter 对应的属性名与参数类型的映射  
getTypes   Map<String, Class<?>>   用于保存 getter 对应的属性名与返回值类型的映射  
caseInsensitivePropertyMap   Map<String, String>    用于保存大写属性名与属性名之间的映射,比如 <NAME, name>  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzyxw.html