zoukankan      html  css  js  c++  java
  • Mybatis框架基础支持层——反射工具箱之MetaClass(7)

    简介:MetaClass是Mybatis对类级别的元信息的封装和处理,通过与属性工具类的结合, 实现了对复杂表达式的解析,实现了获取指定描述信息的功能

    public class MetaClass {
    
        private ReflectorFactory reflectorFactory;
        private Reflector reflector;
    
    
        /**
         * 构造函数私有
         */
        private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
            this.reflectorFactory = reflectorFactory;
            this.reflector = reflectorFactory.findForClass(type);
        }
    
        /**
         * 调用构造方法创建MetaClass
         */
        public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
            return new MetaClass(type, reflectorFactory);
        }
    
        /**
         * 通过属性名称, 获取属性的MetaClass(解决成员变量是类的情况)
         */
        public MetaClass metaClassForProperty(String name) {
            Class<?> propType = reflector.getGetterType(name);
            return MetaClass.forClass(propType, reflectorFactory);
        }
    
        public String findProperty(String name) {
            StringBuilder prop = buildProperty(name, new StringBuilder());
            return prop.length() > 0 ? prop.toString() : null;
        }
    
        public String findProperty(String name, boolean useCamelCaseMapping) {
            if (useCamelCaseMapping) {
                name = name.replace("_", "");
            }
            return findProperty(name);
        }
    
        public String[] getGetterNames() {
            return reflector.getGetablePropertyNames();
        }
    
        public String[] getSetterNames() {
            return reflector.getSetablePropertyNames();
        }
    
        public Class<?> getSetterType(String name) {
            PropertyTokenizer prop = new PropertyTokenizer(name);
            if (prop.hasNext()) {
                MetaClass metaProp = metaClassForProperty(prop.getName());
                return metaProp.getSetterType(prop.getChildren());
            } else {
                return reflector.getSetterType(prop.getName());
            }
        }
    
        public Class<?> getGetterType(String name) {
            PropertyTokenizer prop = new PropertyTokenizer(name);
            if (prop.hasNext()) {
                MetaClass metaProp = metaClassForProperty(prop);
                return metaProp.getGetterType(prop.getChildren());
            }
            // issue #506. Resolve the type inside a Collection Object
            return getGetterType(prop);
        }
    
        private MetaClass metaClassForProperty(PropertyTokenizer prop) {
            Class<?> propType = getGetterType(prop);
            return MetaClass.forClass(propType, reflectorFactory);
        }
    
        private Class<?> getGetterType(PropertyTokenizer prop) {
            Class<?> type = reflector.getGetterType(prop.getName());
            if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
                Type returnType = getGenericGetterType(prop.getName());
                if (returnType instanceof ParameterizedType) {
                    Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();
                    if (actualTypeArguments != null && actualTypeArguments.length == 1) {
                        returnType = actualTypeArguments[0];
                        if (returnType instanceof Class) {
                            type = (Class<?>) returnType;
                        } else if (returnType instanceof ParameterizedType) {
                            type = (Class<?>) ((ParameterizedType) returnType).getRawType();
                        }
                    }
                }
            }
            return type;
        }
    
        private Type getGenericGetterType(String propertyName) {
            try {
                Invoker invoker = reflector.getGetInvoker(propertyName);
                if (invoker instanceof MethodInvoker) {
                    Field _method = MethodInvoker.class.getDeclaredField("method");
                    _method.setAccessible(true);
                    Method method = (Method) _method.get(invoker);
                    return TypeParameterResolver.resolveReturnType(method, reflector.getType());
                } else if (invoker instanceof GetFieldInvoker) {
                    Field _field = GetFieldInvoker.class.getDeclaredField("field");
                    _field.setAccessible(true);
                    Field field = (Field) _field.get(invoker);
                    return TypeParameterResolver.resolveFieldType(field, reflector.getType());
                }
            } catch (NoSuchFieldException e) {
            } catch (IllegalAccessException e) {
            }
            return null;
        }
    
        public boolean hasSetter(String name) {
            PropertyTokenizer prop = new PropertyTokenizer(name);
            if (prop.hasNext()) {
                if (reflector.hasSetter(prop.getName())) {
                    MetaClass metaProp = metaClassForProperty(prop.getName());
                    return metaProp.hasSetter(prop.getChildren());
                } else {
                    return false;
                }
            } else {
                return reflector.hasSetter(prop.getName());
            }
        }
    
        public boolean hasGetter(String name) {
            PropertyTokenizer prop = new PropertyTokenizer(name);
            if (prop.hasNext()) {
                if (reflector.hasGetter(prop.getName())) {
                    MetaClass metaProp = metaClassForProperty(prop);
                    return metaProp.hasGetter(prop.getChildren());
                } else {
                    return false;
                }
            } else {
                return reflector.hasGetter(prop.getName());
            }
        }
    
        public Invoker getGetInvoker(String name) {
            return reflector.getGetInvoker(name);
        }
    
        public Invoker getSetInvoker(String name) {
            return reflector.getSetInvoker(name);
        }
    
        /**
         * 解析属性表达式 会去寻找reflector中是否有对应的的属性
         */
        private StringBuilder buildProperty(String name, StringBuilder builder) {
            // 解析属性表达式
            PropertyTokenizer prop = new PropertyTokenizer(name);
            // 是否有子表达式
            if (prop.hasNext()) {
                // 查找对应的属性
                String propertyName = reflector.findPropertyName(prop.getName());
                if (propertyName != null) {
                    // 追加属性名
                    builder.append(propertyName);
                    builder.append(".");
                    // 创建对应的 MetaClass 对象
                    MetaClass metaProp = metaClassForProperty(propertyName);
                    // 解析子表达式, 递归
                    metaProp.buildProperty(prop.getChildren(), builder);
                }
            } else {
                // 根据名称查找属性
                String propertyName = reflector.findPropertyName(name);
                if (propertyName != null) {
                    builder.append(propertyName);
                }
            }
            return builder;
        }
    
        public boolean hasDefaultConstructor() {
            return reflector.hasDefaultConstructor();
        }
    
    }

    理解了这个方法(递归, 该类中有很多类似的), 就可以很好的对这个类进行理解, 以查找(richType.richProperty)为例:

    1. 通过 PropertyTokenizer 对表达式进行解析, 得到当前的 name = richType,  children = richProperty
    2. 从 reflector 中查找该 richType 属性
    3. 将 richType 添加到 builder 中
    4. 使用 metaClassForProperty 创建 richType 的 MetaClass。
    5. 递归调用自身来处理子表达式

    退出的条件就是没有子表达式。 这个就是为了, 我们类中有成员变量是类, 我们可以通过其找到他们的所有类及其属性
    注意, 在此过程中, ReflectorFactory 一直是同一个, 而其内部缓存了多个 Reflector 对象。

  • 相关阅读:
    数据结构与算法之二叉查找树精简要点总结
    数据结构与算法之并查集的精简要点总结
    数组嵌套实现哈希函数的数据分片应用
    InfluxDB 写入&查询 Qt工程(C++ 客户端 API)
    关于Maven中<packaging>产生的一些问题
    Spring Boot:The field file exceeds its maximum permitted size of 1048576 bytes
    Npm管理命令
    ES6转ES5(Babel转码器)
    IOC容器中的依赖注入(一)
    Nginx常用部分命令
  • 原文地址:https://www.cnblogs.com/wly1-6/p/10333917.html
Copyright © 2011-2022 走看看