Mybatis源码学习之路三反射模块核心类Reflector类详解

前言:

Reflector是Mybatis中反射模块的基础,每个Reflector对象都对应一个类,而Reflector中缓存了反射操作需要使用的类的原信息

本片博客详解了下Reflector中各个方法是如何将属性中所需的信息进行填充的,代码中都写入的比较详细的注释

Reflector类解析:

类成员变量解析:

//对应的Class类型
private final Class type;
//可读属性的名称集合,可读属性就是存在相应get方法的属性
private final String[] readablePropertyNames;
//可写属性的名称集合,可写属性就是存在相应set方法的属性
private final String[] writeablePropertyNames;
//set方法的Map,key是属性的名称,而value则是Invoker对象,是对setter方法对应Method对象的封装
private final Map setMethods = new HashMap();
//get方法的Map,key是属性的名称,而value则是Invoker对象,是对getter方法对应Method对象的封装
private final Map getMethods = new HashMap();
//setter方法中参数值类型的Map,key为属性名称,value为对应的参数类型
private final Map> setTypes = new HashMap();
//getter方法中返回值类型的Map,key为属性名称,value为对应的返回值类型
private final Map> getTypes = new HashMap();
//type指向类型的默认构造函数
private Constructor defaultConstructor;
//所有属性名称的集合,key为属性名称大写,value为对应的属性名称
private Map caseInsensitivePropertyMap = new HashMap();

构造器解析:

//构造器的参数为Class对象,表明需要封装的类对象
public Reflector(Class clazz) {
        //为type变量赋值
        this.type = clazz;
        //为defaultConstructor变量赋值
        this.addDefaultConstructor(clazz);
        //将相应的get方法添加到getMethods中
        this.addGetMethods(clazz);
        //将相应的set方法添加到setMethods中
        this.addSetMethods(clazz);
        //将相应setter方法的参数类型添加到setTypes中,将相应的getter方法的返回值类型添加到getTypes中
        this.addFields(clazz);
        //为readablePropertyNames变量赋值
        this.readablePropertyNames = (String[])this.getMethods.keySet().toArray(new String[this.getMethods.keySet().size()]);
        //为writeablePropertyNames变量赋值
        this.writeablePropertyNames = (String[])this.setMethods.keySet().toArray(new String[this.setMethods.keySet().size()]);
        String[] var2 = this.readablePropertyNames;
        int var3 = var2.length;

        int var4;
        String propName;
        for(var4 = 0; var4 < var3; ++var4) {
            propName = var2[var4];
//将可读属性添加到caseInsensitivePropertyMap中            this.caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
        }

        var2 = this.writeablePropertyNames;
        var3 = var2.length;

        for(var4 = 0; var4 < var3; ++var4) {
            propName = var2[var4];
//将可写属性添加到caseInsensitivePropertyMap中            this.caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
        }

    }

获取该类型对应的默认构造器并进行赋值

private void addDefaultConstructor(Class clazz) {
        //获取所有声明的构造器对象
        Constructor[] consts = clazz.getDeclaredConstructors();
        Constructor[] var3 = consts;
        int var4 = consts.length;
        //循环该构造器对象数组
        for(int var5 = 0; var5 < var4; ++var5) {
            Constructor constructor = var3[var5];
            //判断若该构造器的参数数量为0表示默认构造器
            if (constructor.getParameterTypes().length == 0) {
                //判断是否可以访问私有方法
                if (canAccessPrivateMethods()) {
                    try {
                        //若可以的话,设置该方法的访问权限为true
                        constructor.setAccessible(true);
                    } catch (Exception var8) {
                    }
                }

                if (constructor.isAccessible()) {
                    this.defaultConstructor = constructor;
                }
            }
        }

    }
addGetMethods方法用于向getMethods和getTypes两个属性注入getter方法名称对应Method以及对应返回值类型的Map中
private void addGetMethods(Class cls) {
        Map> conflictingGetters = new HashMap();
        //获取该Class对象包含的所有公有方法,包括父类或父接口继承而来的方法(去重)
        Method[] methods = this.getClassMethods(cls);
        Method[] var4 = methods;
        int var5 = methods.length;
        //遍历所有方法对应的Method对象
        for(int var6 = 0; var6 < var5; ++var6) {
            Method method = var4[var6];
            //获取属性对应的getter方法应该没有参数类型,这里进行过滤
            if (method.getParameterTypes().length <= 0) {
                String name = method.getName();
                //通过方法名称判断是否为getter方法(按照javabean规范查找getter方法)
                //情况一:以get开头,并且名称长度大于3的方法为getter方法
                //情况二:以is开头,并且名称长度大于2的方法为getter方法
                if (name.startsWith("get") && name.length() > 3 || name.startsWith("is") && name.length() > 2) {
                    //获取属性名称,即去掉名称开头的get或is,并将首字母小写
                    name = PropertyNamer.methodToProperty(name);
                    //将名称和method的映射关系添加到conflictingGetters的Map中
                    this.addMethodConflict(conflictingGetters, name, method);
                }
            }
        }
        //解决冲突并将值添加到相应的getMethods和getTypes中去
        this.resolveGetterConflicts(conflictingGetters);
    }
private Method[] getClassMethods(Class cls) {
        Map uniqueMethods = new HashMap();
        for(Class currentClass = cls; currentClass != null && currentClass != Object.class; currentClass = currentClass.getSuperclass()) {
            //getDeclaredMethods方法用于获取Class对象的所有公有的方法,包括从父类或父接口继承而来的方法
            //注意和getMethods()方法的区别,该方法只获取Class对象的所有方法,但不包括从父类或父接口继承而来的方法
            this.addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
            //获取其实现的接口对应的Class对象
            Class[] interfaces = currentClass.getInterfaces();
            Class[] var5 = interfaces;
            int var6 = interfaces.length;

            //遍历接口类型数组,并将其接口的方法添加到Map中
            for(int var7 = 0; var7 < var6; ++var7) {
                Class anInterface = var5[var7];
                this.addUniqueMethods(uniqueMethods, anInterface.getMethods());
            }
        }
        //获取方法Method对象集合并转化为数组返回
        Collection methods = uniqueMethods.values();
        return (Method[])methods.toArray(new Method[methods.size()]);
    }
private void addUniqueMethods(Map uniqueMethods, Method[] methods) {
        Method[] var3 = methods;
        int var4 = methods.length;

        //遍历Method对象数组
        for(int var5 = 0; var5 < var4; ++var5) {
            Method currentMethod = var3[var5];
            //忽略桥接方法,桥接方法是为了使Java的泛型方法生成的字节码和1.5版本之前的字节码兼容而由编译期自动生成的方法
            if (!currentMethod.isBridge()) {
                //获取Method对象的标签(返回类型名称+参数名称组合而成的字符串)
                String signature = this.getSignature(currentMethod);
                if (!uniqueMethods.containsKey(signature)) {
                    if (canAccessPrivateMethods()) {
                        try {
                            currentMethod.setAccessible(true);
                        } catch (Exception var9) {
                        }
                    }

                    uniqueMethods.put(signature, currentMethod);
                }
            }
        }

    }
//判断私有方法是否能够访问
    private static boolean canAccessPrivateMethods() {
        try {
            SecurityManager securityManager = System.getSecurityManager();
            if (null != securityManager) {
                securityManager.checkPermission(new ReflectPermission("suppressAccessChecks"));
            }

            return true;
        } catch (SecurityException var1) {
            return false;
        }
    }
private String getSignature(Method method) {
        StringBuilder sb = new StringBuilder();
        Class returnType = method.getReturnType();
        if (returnType != null) {
            sb.append(returnType.getName()).append('#');
        }

        sb.append(method.getName());
        Class[] parameters = method.getParameterTypes();

        for(int i = 0; i < parameters.length; ++i) {
            if (i == 0) {
                sb.append(':');
            } else {
                sb.append(',');
            }

            sb.append(parameters[i].getName());
        }

        return sb.toString();
    }
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)list).add(method);
    }
private void resolveGetterConflicts(Map> conflictingGetters) {
        //获取Map参数的迭代器
        Iterator var2 = conflictingGetters.entrySet().iterator();

        while(var2.hasNext()) {
            //获取Entry对象
            Map.Entry> entry = (Map.Entry)var2.next();
            Method winner = null;
            //获取属性名称
            String propName = (String)entry.getKey();
            //获取属性名称对应的getter方法集合,存在集合的原因在于父类中也可能存在同名的getter方法
            Iterator var6 = ((List)entry.getValue()).iterator();

            //开始循环,最终结果是获取子类的getter方法
            while(var6.hasNext()) {
                //循环获取getter方法对应的Method对象
                Method candidate = (Method)var6.next();
                if (winner == null) {
                    //第一次循环时将Method对象赋值为winner,然后继续循环
                    winner = candidate;
                } else {
                    //获取前一个Method对象的返回值类型
                    Class winnerType = winner.getReturnType();
                    //获取当前Method对象的返回值类型
                    Class candidateType = candidate.getReturnType();
                    //判断两个getter方法的返回值类型是否相同
                    if (candidateType.equals(winnerType)) {
                        //判断当前getter方法的返回值类型是否Boolean类型
                        if (!Boolean.TYPE.equals(candidateType)) {
                            throw new ReflectionException("Illegal overloaded getter method with ambiguous type for property " + propName + " in class " + winner.getDeclaringClass() + ". This breaks the JavaBeans specification and can cause unpredictable results.");
                        }
                        //判断当前getter方法的名称是否已is开头
                        if (candidate.getName().startsWith("is")) {
                            winner = candidate;
                        }
                        //判断当前getter方法的返回值类型是否是前一个getter方法的返回值类型的超类或超接口
                    } else if (!candidateType.isAssignableFrom(winnerType)) {
                        if (!winnerType.isAssignableFrom(candidateType)) {
                            throw new ReflectionException("Illegal overloaded getter method with ambiguous type for property " + propName + " in class " + winner.getDeclaringClass() + ". This breaks the JavaBeans specification and can cause unpredictable results.");
                        }

                        winner = candidate;
                    }
                }
            }
            //将该属性对应getter方法以及该方法的返回值类型分别添加到getMethods和getTypes属性中
            this.addGetMethod(propName, winner);
        }
    }
private void addGetMethod(String name, Method method) {
        if (this.isValidPropertyName(name)) {
            this.getMethods.put(name, new MethodInvoker(method));
            //TypeParameterResolver的功能:当存在复杂的继承关系以及泛型定义时,可以帮助解析字段、方法参数或方法返回值的类型
            Type returnType = TypeParameterResolver.resolveReturnType(method, this.type);
            this.getTypes.put(name, this.typeToClass(returnType));
        }
    }
private boolean isValidPropertyName(String name) {
        //名称不以$符号开头,不等于serialVersionUID,不等于class几位有效属性名
        return !name.startsWith("$") && !"serialVersionUID".equals(name) && !"class".equals(name);
    }
private Class typeToClass(Type src) {
        Class result = null;
        if (src instanceof Class) {
            result = (Class)src;
        } else if (src instanceof ParameterizedType) {
            result = (Class)((ParameterizedType)src).getRawType();
        } else if (src instanceof GenericArrayType) {
            Type componentType = ((GenericArrayType)src).getGenericComponentType();
            if (componentType instanceof Class) {
                result = Array.newInstance((Class)componentType, 0).getClass();
            } else {
                Class componentClass = this.typeToClass(componentType);
                result = Array.newInstance(componentClass, 0).getClass();
            }
        }

        if (result == null) {
            result = Object.class;
        }

        return result;
    }
addSetMethods方法最终用于添加setMethods以及setTypes属性:
private void addSetMethods(Class cls) {
        Map> conflictingSetters = new HashMap();
        //获取该Class对象包含的所有公共方法,包括父类或父接口继承而来的方法(去重)
        Method[] methods = this.getClassMethods(cls);
        Method[] var4 = methods;
        int var5 = methods.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            Method method = var4[var6];
            String name = method.getName();
            //setter方法都有对应的参数,所有这里没有像getter方法那样判断参数类型为空
            if (name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) {
                //获取属性名称,即去掉名称开头的get或is,并将首字母小写
                name = PropertyNamer.methodToProperty(name);
                //将名称和method的映射关系添加到conflictingGetters的Map中
                this.addMethodConflict(conflictingSetters, name, method);
            }
        }
        //解决冲突并将值添加到相应的setMethods和setTypes中去
        this.resolveSetterConflicts(conflictingSetters);
    }
private void resolveSetterConflicts(Map> conflictingSetters) {
        Iterator var2 = conflictingSetters.keySet().iterator();
        //遍历参数Map
        while(var2.hasNext()) {
            //获取key即属性名称
            String propName = (String)var2.next();
            //获取value及属性名称对应的setter方法集合
            List setters = (List)conflictingSetters.get(propName);
            //获取属性名称对应的返回值类型
            Class getterType = (Class)this.getTypes.get(propName);
            //定义最终匹配的方法
            Method match = null;
            //定义反射异常
            ReflectionException exception = null;
            Iterator var8 = setters.iterator();
            //开始遍历属性名称对应的setter方法集合
            while(var8.hasNext()) {
                Method setter = (Method)var8.next();
                //获取setter方法的第一个参数类型
                Class paramType = setter.getParameterTypes()[0];
                //如果参数类型和该属性对应的getter方法返回类型相同则设置匹配对象为该当前setter方法,然后退出循环
                if (paramType.equals(getterType)) {
                    match = setter;
                    break;
                }

                if (exception == null) {
                    try {
                        //比较当前setter方法和前一个setter方法,看设置那个setter方法为匹配方法
                        match = this.pickBetterSetter(match, setter, propName);
                    } catch (ReflectionException var12) {
                        match = null;
                        exception = var12;
                    }
                }
            }

            if (match == null) {
                throw exception;
            }

            this.addSetMethod(propName, match);
        }

    }
private Method pickBetterSetter(Method setter1, Method setter2, String property) {
        if (setter1 == null) {
            //当第一次循环时,前一个setter为空无法比较,直接返回当前setter
            return setter2;
        } else {
            Class paramType1 = setter1.getParameterTypes()[0];
            Class paramType2 = setter2.getParameterTypes()[0];
            //若setter1中参数类型是setter2中参数类型的父类或父接口,返回setter2方法
            //即优先获取子类的setter方法
            if (paramType1.isAssignableFrom(paramType2)) {
                return setter2;
            } else if (paramType2.isAssignableFrom(paramType1)) {
                return setter1;
            } else {
                throw new ReflectionException("Ambiguous setters defined for property '" + property + "' in class '" + setter2.getDeclaringClass() + "' with types '" + paramType1.getName() + "' and '" + paramType2.getName() + "'.");
            }
        }
    }
private void addSetMethod(String name, Method method) {
        if (this.isValidPropertyName(name)) {
            //将setter方法设置到setMethods属性中
            this.setMethods.put(name, new MethodInvoker(method));
            Type[] paramTypes = TypeParameterResolver.resolveParamTypes(method, this.type);
            //将setter方法的参数值类型设置到setTypes属性中去
            this.setTypes.put(name, this.typeToClass(paramTypes[0]));
        }

    }

addField字段也是用于填充setMethods、getMethods、setTypes以及getTypes属性

rivate void addFields(Class clazz) {
        //获取该Class对象所有的公有属性,包括父类或父接口中定义的属性
        Field[] fields = clazz.getDeclaredFields();
        Field[] var3 = fields;
        int var4 = fields.length;

        //遍历属性集合
        for(int var5 = 0; var5 < var4; ++var5) {
            Field field = var3[var5];
            if (canAccessPrivateMethods()) {
                try {
                    //设置该属性可编辑修改
                    field.setAccessible(true);
                } catch (Exception var8) {
                }
            }

            if (field.isAccessible()) {
                //判断setter方法映射集合中是否包含该属性名
                if (!this.setMethods.containsKey(field.getName())) {
                    int modifiers = field.getModifiers();
                    //获取该属性的修饰符,并判断该属性不是final或不是类属性
                    if (!Modifier.isFinal(modifiers) || !Modifier.isStatic(modifiers)) {
                        this.addSetField(field);
                    }
                }
                
                //判断getter方法映射集合中是否包含该属性名
                if (!this.getMethods.containsKey(field.getName())) {
                    this.addGetField(field);
                }
            }
        }

        //如果存在父类,将父类的属性添加进去
        if (clazz.getSuperclass() != null) {
            this.addFields(clazz.getSuperclass());
        }

    }
//类似于addSetMethod,这里不再详解
    private void addSetField(Field field) {
        if (this.isValidPropertyName(field.getName())) {
            this.setMethods.put(field.getName(), new SetFieldInvoker(field));
            Type fieldType = TypeParameterResolver.resolveFieldType(field, this.type);
            this.setTypes.put(field.getName(), this.typeToClass(fieldType));
        }

    }
//类似于addGetMethod方法,这里不再详解
    private void addGetField(Field field) {
        if (this.isValidPropertyName(field.getName())) {
            this.getMethods.put(field.getName(), new GetFieldInvoker(field));
            Type fieldType = TypeParameterResolver.resolveFieldType(field, this.type);
            this.getTypes.put(field.getName(), this.typeToClass(fieldType));
        }

    }

 

 

 

 

 

你可能感兴趣的:(mybatis,Mybaits源码)