Mybatis的Reflector解析

Mybatis的MetaObject解析:[url]http://donald-draper.iteye.com/admin/blogs/2338818[/url]
在上篇分析MetaObejct时候,MetaObejct的方法的实现是依赖ObjectWrapper,ObjectWrapper依赖于MetaClass,而MetaClass依赖于Reflector,这一节我们就来看看Reflector
//Reflector
public class Reflector
{
private static boolean classCacheEnabled = true;
private static final String EMPTY_STRING_ARRAY[] = new String[0];
private static final Map REFLECTOR_MAP = new ConcurrentHashMap();
private Class type;
private String readablePropertyNames[];//可读属性名
private String writeablePropertyNames[];//可写属性名
private Map setMethods;Map
private Map getMethods;Map
private Map setTypes;Map
private Map getTypes;Map
private Constructor defaultConstructor;//默认构造函数
private Map caseInsensitivePropertyMap;//大小写不敏感属性Map
//构造Class对应的Reflector
public static Reflector forClass(Class clazz)
{
if(classCacheEnabled)
{
//如果缓存状态开启,则从REFLECTOR_MAP获取对应的Reflector,没有则重新构建
Reflector cached = (Reflector)REFLECTOR_MAP.get(clazz);
if(cached == null)
{
cached = new Reflector(clazz);
REFLECTOR_MAP.put(clazz, cached);
}
return cached;
} else
{
return new Reflector(clazz);
}
}
private Reflector(Class clazz)
{
readablePropertyNames = EMPTY_STRING_ARRAY;//可读属性名
writeablePropertyNames = EMPTY_STRING_ARRAY;//可写属性名
setMethods = new HashMap();//Set方法Map
getMethods = new HashMap();//Get方法Map
setTypes = new HashMap();
getTypes = new HashMap();
caseInsensitivePropertyMap = new HashMap();//大小写不敏感属性Map
type = clazz;
addDefaultConstructor(clazz);
addGetMethods(clazz);
addSetMethods(clazz);
addFields(clazz);
readablePropertyNames = (String[])getMethods.keySet().toArray(new String[getMethods.keySet().size()]);
writeablePropertyNames = (String[])setMethods.keySet().toArray(new String[setMethods.keySet().size()]);
//将可读属性添加大小写不敏感属性Map
String arr$[] = readablePropertyNames;
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; i$++)
{
String propName = arr$[i$];
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
//将可写属性添加大小写不敏感属性Map
arr$ = writeablePropertyNames;
len$ = arr$.length;
for(int i$ = 0; i$ < len$; i$++)
{
String propName = arr$[i$];
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}

}
}

来看addDefaultConstructor
初始化默认构造函数为,无参构造函数
private void addDefaultConstructor(Class clazz)
{
Constructor consts[] = clazz.getDeclaredConstructors();
Constructor arr$[] = consts;
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; i$++)
{
Constructor constructor = arr$[i$];
if(constructor.getParameterTypes().length != 0)
continue;
if(canAccessPrivateMethods())
try
{
constructor.setAccessible(true);
}
catch(Exception e) { }
if(constructor.isAccessible())
defaultConstructor = constructor;
}

}

来看addGetMethods
将Class的Get方法添加到
 private void addGetMethods(Class cls)
{
Map conflictingGetters = new HashMap();
Method methods[] = getClassMethods(cls);
Method arr$[] = methods;
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; i$++)
{
Method method = arr$[i$];
String name = method.getName();
if(name.startsWith("get") && name.length() > 3)
{
if(method.getParameterTypes().length == 0)
{
name = PropertyNamer.methodToProperty(name);
//将name对应的get方法添加到conflictingGetters-Map中
addMethodConflict(conflictingGetters, name, method);
}
continue;
}
if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0)
{
name = PropertyNamer.methodToProperty(name);
addMethodConflict(conflictingGetters, name, method);
}
}
//解决方法冲突
resolveGetterConflicts(conflictingGetters);
}
private void addMethodConflict(Map conflictingMethods, String name, Method method)
{
List list = (List)conflictingMethods.get(name);
if(list == null)
{
list = new ArrayList();
conflictingMethods.put(name, list);
}
list.add(method);
}

private void resolveGetterConflicts(Map conflictingGetters)
{
for(Iterator i$ = conflictingGetters.keySet().iterator(); i$.hasNext();)
{
String propName = (String)i$.next();
List getters = (List)conflictingGetters.get(propName);
Iterator iterator = getters.iterator();
Method firstMethod = (Method)iterator.next();
if(getters.size() == 1)
{
addGetMethod(propName, firstMethod);
} else
{
Method getter = firstMethod;
Class getterType = firstMethod.getReturnType();
do
{
if(!iterator.hasNext())
break;
Method method = (Method)iterator.next();
Class methodType = method.getReturnType();
if(methodType.equals(getterType))
throw new ReflectionException((new StringBuilder()).append("Illegal overloaded getter method with ambiguous type for property ").append(propName).append(" in class ").append(firstMethod.getDeclaringClass()).append(". This breaks the JavaBeans ").append("specification and can cause unpredicatble results.").toString());
if(!methodType.isAssignableFrom(getterType))
if(getterType.isAssignableFrom(methodType))
{
getter = method;
getterType = methodType;
} else
{
throw new ReflectionException((new StringBuilder()).append("Illegal overloaded getter method with ambiguous type for property ").append(propName).append(" in class ").append(firstMethod.getDeclaringClass()).append(". This breaks the JavaBeans ").append("specification and can cause unpredicatble results.").toString());
}
} while(true);
//将name对应的get方法添加到getMethods集合中
addGetMethod(propName, getter);
}
}

}
//将name对应的get方法添加到getMethods集合中
private void addGetMethod(String name, Method method)
{
if(isValidPropertyName(name))
{
getMethods.put(name, new MethodInvoker(method));
getTypes.put(name, method.getReturnType());
}
}

来看addSetMethods
private void addSetMethods(Class cls)
{
Map conflictingSetters = new HashMap();
Method methods[] = getClassMethods(cls);
Method arr$[] = methods;
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; i$++)
{
Method method = arr$[i$];
String name = method.getName();
if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1)
{
name = PropertyNamer.methodToProperty(name);
//将name对应的set方法添加到conflictingSetters-Map中
addMethodConflict(conflictingSetters, name, method);
}
}
//解决方法冲突
resolveSetterConflicts(conflictingSetters);
}

private void addMethodConflict(Map conflictingMethods, String name, Method method)
{
List list = (List)conflictingMethods.get(name);
if(list == null)
{
list = new ArrayList();
conflictingMethods.put(name, list);
}
list.add(method);
}

private void resolveSetterConflicts(Map conflictingSetters)
{
Iterator i$ = conflictingSetters.keySet().iterator();
do
{
if(!i$.hasNext())
break;
String propName = (String)i$.next();
List setters = (List)conflictingSetters.get(propName);
Method firstMethod = (Method)setters.get(0);
if(setters.size() == 1)
{
addSetMethod(propName, firstMethod);
continue;
}
Class expectedType = (Class)getTypes.get(propName);
if(expectedType == null)
throw new ReflectionException((new StringBuilder()).append("Illegal overloaded setter method with ambiguous type for property ").append(propName).append(" in class ").append(firstMethod.getDeclaringClass()).append(". This breaks the JavaBeans ").append("specification and can cause unpredicatble results.").toString());
Iterator methods = setters.iterator();
Method setter = null;
do
{
if(!methods.hasNext())
break;
Method method = (Method)methods.next();
if(method.getParameterTypes().length != 1 || !expectedType.equals(method.getParameterTypes()[0]))
continue;
setter = method;
break;
} while(true);
if(setter == null)
throw new ReflectionException((new StringBuilder()).append("Illegal overloaded setter method with ambiguous type for property ").append(propName).append(" in class ").append(firstMethod.getDeclaringClass()).append(". This breaks the JavaBeans ").append("specification and can cause unpredicatble results.").toString());
//将对应的set方法添加到setMethods-map中
addSetMethod(propName, setter);
} while(true);
}

private void addSetMethod(String name, Method method)
{
if(isValidPropertyName(name))
{
setMethods.put(name, new MethodInvoker(method));
setTypes.put(name, method.getParameterTypes()[0]);
}
}

来看addFields
private void addFields(Class clazz)
{
Field fields[] = clazz.getDeclaredFields();
Field arr$[] = fields;
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; i$++)
{
Field field = arr$[i$];
if(canAccessPrivateMethods())
try
{
field.setAccessible(true);
}
catch(Exception e) { }
if(!field.isAccessible())
continue;
if(!setMethods.containsKey(field.getName()))
addSetField(field);
if(!getMethods.containsKey(field.getName()))
addGetField(field);
}

if(clazz.getSuperclass() != null)
addFields(clazz.getSuperclass());
}
//将Field的对应set方法,及参数类型添加到setMethods,setTypes-Map中
private void addSetField(Field field)
{
if(isValidPropertyName(field.getName()))
{
setMethods.put(field.getName(), new SetFieldInvoker(field));
setTypes.put(field.getName(), field.getType());
}
}
//将Field的对应get方法,及参数类型添加到setMethods,setTypes-Map中
private void addGetField(Field field)
{
if(isValidPropertyName(field.getName()))
{
getMethods.put(field.getName(), new GetFieldInvoker(field));
getTypes.put(field.getName(), field.getType());
}
}

总结:
[color=blue]从以上分析,Reflector构造函数,所做的工作为,初始构造函数,将Class的set与get方法及参数添加到setMethods,getMethods,setTypes,getTypes对应的Map中,setMethods,getMethods Map的key属性名,value为对应的方法,然后初始化可读,可写,及大小写不明感属性集合。[/color]

你可能感兴趣的:(Mybatis,Reflector,Mybatis)