聊聊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的构造方法
通过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);
}
}
- type记录class的类型
- addDefaultConstructor是通过反射得到Class的无参构造方法
- addGetMethods()方法就是用来读取Class的getter方法,然后放入getMethods集合中和getTypes集合中,
- addSetMethods()方法就是读取Class文件的setter方法,放入setMethods方法列表集合和setTypes类型列表集合中
- addFields()方法是针对class中没有getter setter方法的字段生成GetFieldInvoker类来放入getMethods、getTypes、setMethods和setTypes集合中
- 然后初始化readablePropertyNames和writeablePropertyNames,readablePropertyNames是getter的属性列表集合,writeablePropertyNames是setter的属性列表集合
- 把readablePropertyNames和writeablePropertyNames中全部转为大写,保存到caseInsensitivePropertyMap中,key是属性名的大写,value是属性名
Reflector的 addGetMethods()
步骤三中我们提到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);
}
- 调用getClassMethods(cls);获取方法信息,点进去这个方法可以看到定义了一个map集合
Map<String, Method> uniqueMethods = new HashMap<String, Method>();
它的key是返回值类型#方法名称:参数类型:参数类型。。。,value是Method对象,key保证全局唯一,使用map能进行去重 - 获取到这些methods对象后,循环遍历,找出getter方法来,放入conflictingGetters集合中,key是属性名。value是对应的getter方法的集合,为什么是集合呢,因为有可能存在方法的重写
- 最后resolveGetterConflicts()方法解决签名的冲突,就是比较getter方法的返回值,取子类的getter方法,在这个方法里调用addGetMethod把对应的Method生成MethodInvoker对象保存到getMethods中
总结
今天主要介绍了一下mybatis反射模块的Reflector类的构造方法的一些细节和用到成员变量,希望mybatis源码的分析能对你有所帮助。
❤️ 感谢大家
如果你觉得这篇内容对你挺有有帮助的话:
- 欢迎关注我❤️,点赞??,评论?,转发?