聊聊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()
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集合
它的key是傳回值類型#方法名稱:參數類型:參數類型。。。,value是Method對象,key保證全局唯一,使用map能進行去重Map<String, Method> uniqueMethods = new HashMap<String, Method>();
- 擷取到這些methods對象後,循環周遊,找出getter方法來,放入conflictingGetters集合中,key是屬性名。value是對應的getter方法的集合,為什麼是集合呢,因為有可能存在方法的重寫
- 最後resolveGetterConflicts()方法解決簽名的沖突,就是比較getter方法的傳回值,取子類的getter方法,在這個方法裡調用addGetMethod把對應的Method生成MethodInvoker對象儲存到getMethods中
總結
❤️ 感謝大家
- 歡迎關注我❤️,點贊??,評論?,轉發?