Mybatis的Reflector解析

Mybatis的MetaObject解析: http://donald-draper.iteye.com/admin/blogs/2338818
在上篇分析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<String,MethodInvoker>
    private Map getMethods;Map<String,MethodInvoker>
    private Map setTypes;Map<String,Class>
    private Map getTypes;Map<String,Class>
    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());
        }
    }

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

猜你喜欢

转载自donald-draper.iteye.com/blog/2338825