手敲Mybatis-反射工具天花板

news2024/11/18 22:40:00

历时漫长的岁月,终于鼓起勇气继续研究Mybatis的反射工具类们,简直就是把反射玩出花,但是理解起来还是很有难度的,涉及的内容代码也颇多,所以花费时间也比较浩大,不过当了解套路每个类的功能也好,设计也好,基本也可以浓缩成一句话理解,心中有了系统也好似没有那么难理解了,本节如在工作中使用到此场景,可以拿来当作工具直接使用。

  1. 前言-为什么使用反射

在手敲Mybatis-数据源池化处理实现那一节,我们留下了坑需要填,在获取连接时,数据库连接的设置还是硬编码,如果我们此时xml文件又需要新增加一些属性,就需要进行修改代码,会发现代码设计不太灵活,本节就为了解决此问题,来一起写一个很强大的反射工具类。

  1. UML类图-类关系介绍

MyBatis设计将分为以下几个类,元类、元对象、对象包装器、反射器、调用者、对象工厂,下面就介绍这几个设计都是干什么的:

SystemMetaObject:系统入口,万物的开始,系统级别的元对象

MetaObject:元对象,外部系统调用入口,封装了包装器对象,在构造方法中使用策略模式来调用不同的对象包装器

MetaClass:元类,通过对象包装器进入,此类是对反射器的封装并进一步进行处理某些场景复杂操作

Reflector:反射器,解析对象的属性、方法、类型的解析器,最后组装起来,提供基础的方法获取数据

ObjectWrapper:对象包装器接口,定义对象基本信息

BaseWrapper:基础包装器,抽取共用包装器方法,解析集合获取集合设置集合等处理

BeanWrapper:原生包装器,对bean对象进行处理,由此方法进入MetaClass类最后进入 Reflector反射将对象数据得到。

CollectionWrapper:原生集合包装器

MapWrapper:map集合包装器,处理map对象

ObjectWrapperFactory:对象包装器工厂接口,可以获取对象包装器

DefaultObjectWrapperFactory:实现对象包装器工厂接口

ObjectFactory:对象工厂接口

DefaultObjectFactory:默认对象工厂接口,创建对象实例处理

Invoker: 调用者接口,定义反射调用

MethodInvoker:方法调用者,反射方法的

GetFieldInvoker此类用于执行读取属性值的反射操作

SetFieldInvoker:用于执行设置属性值的反射操作

PropertyNamer:属性命名器,会将方法转换为属性名称

PropertyTokenizer :属性解析器,属性也不只有单一属性也会有复杂属性,例如属性.属性,集合等

执行流程:SystemMetaObject-->MetaObject-->ObjectWrapper-->MetaClass-->Reflector-->Invoker

而属解析器在处理中有时各个类都会用,反射器工具类要用的就这个20个类,想必你通过介绍大大致对它有印象了,可以对应看下uml图理解理解

  1. 完整代码实现

3.1 反射调用者

package df.middleware.mybatis.reflection.invoker

Invoker:反射调用者接口,定义invoke方法,子类具体实现对应的调用者,因为反射调用离不开目标对象和参数,所以此接口统一定义invoke()。

/**
 * @description 调用者接口
 * @date 2022/5/2
 * 此接口的作用统一基于反射处理方法和属性的调用方式,采取策略模式
 */
public interface Invoker {

    /**
     * 执行反射操作
     *
     * @param target 方法或者属性执行的目标对象
     * @param args   方法或者属性执行时依赖的参数
     */
    Object invoke(Object target, Object[] args) throws Exception;

    /**
     *方法或者属性对应的类型
     */
    Class<?> getType();

}

MethodInvoker:方法调用者,构造函数会传对应的目标方method,再通过反射进行调用目标方法

/**
 * @description 方法调用者
 * 用于执行方法的反射操作
 */
public class MethodInvoker implements Invoker {

    private Class<?> type;
    private Method method;
    /**
     * 如果方法是getter方法,则表示返回值类型
     * 如果方法是setter方法,则表示入参类型
     */
    public MethodInvoker(Method method) {
        this.method = method;

        // 利用方法是否有无入参判断方法是get还是set方法,
        // 如果只有一个参数,返回参数类型,否则返回 return 类型
        if (method.getParameterTypes().length == 1) {
            // set方法获取方法入参类型赋给type属性
            type = method.getParameterTypes()[0];
        } else {
            // get方法则获取方法返回类型赋给type属性
            type = method.getReturnType();
        }
    }

    @Override
    public Object invoke(Object target, Object[] args) throws Exception {
        // 执行方法
        return method.invoke(target, args);
    }

    @Override
    public Class<?> getType() {
        return type;
    }

}

GetFieldInvoker:获取属性调用者,构造函数会传目标属性Field,通过反射获取属性值并返回

/**
 * @description getter 调用者
 * 属性是会有set和get的,所以字段会有GetFieldInvoker和SetFieldInvoker
 * 此类用于执行读取属性值的反射操作
 */
public class GetFieldInvoker implements Invoker {

    private Field field;

    public GetFieldInvoker(Field field) {
        this.field = field;
    }

    @Override
    public Object invoke(Object target, Object[] args) throws Exception {
        // 基于反射获取指定属性值
        return field.get(target);
    }

    // 获取对应属性的类型
    @Override
    public Class<?> getType() {
        return field.getType();
    }
}

SetFieldInvoker:设置属性调用者,构造函数会传目标属性Field,通过反射给目标属性设置值,设置是不返回的,这里就返回空

/**
 * @description setter 调用者
 * 用于执行设置属性值的反射操作
 */
public class SetFieldInvoker implements Invoker {

    private Field field;

    public SetFieldInvoker(Field field) {
        this.field = field;
    }

    @Override
    public Object invoke(Object target, Object[] args) throws Exception {
        // 为指定属性设置值的功能
        field.set(target, args[0]);
        return null;
    }

    @Override
    public Class<?> getType() {
        return field.getType();
    }
}

3.2反射器

Reflector:反射器,这个类代码相对很多,大体主要是用反射将对象信息解析出来,如类里的默认构造方法,以及属性和方法等等,解析出来处理成我们想要的数据以后存储各个容器里。这样我们数据有了,还需要添加一些对外获取容器数据的公共方法,这就是这个类的全部职责,其实也还好,就是代码多些,但是知道大致处理内容,也就没有那么难理解了,需要多debug熟悉。

/**
 *  反射器,属性 get/set 的映射器
 * */
public class Reflector {

    private static boolean classCacheEnabled = true;

    private static final String[] EMPTY_STRING_ARRAY = new String[0];
    // 线程安全的缓存
    private static final Map<Class<?>, Reflector> REFLECTOR_MAP = new ConcurrentHashMap<>();

    private Class<?> type;
    /**
     * get 属性列表,可读属性名称数组,用于保存 getter 方法对应的属性名称
     * */
    private String[] readablePropertyNames = EMPTY_STRING_ARRAY;
    /**
     * set 属性列表,可写属性名称数组,用于保存 setter 方法对应的属性名称
     * */
    private String[] writeablePropertyNames = EMPTY_STRING_ARRAY;
    /**
     * set 方法列表,
     * 用于保存属性名称到 Invoke 的映射。setter 方法会被封装到 MethodInvoker 对象中
     * */
    private Map<String, Invoker> setMethods = new HashMap<>();
    /**
     * get 方法列表
     * 用于保存属性名称到 Invoke 的映射。同上,getter 方法也会被封装到 MethodInvoker 对象中
     * */
    private Map<String, Invoker> getMethods = new HashMap<>();
    /**
     * 用于保存 setter 对应的属性名与参数类型的映射
     * */
    private Map<String, Class<?>> setTypes = new HashMap<>();
    /**
     * 用于保存 getter 对应的属性名与返回值类型的映射
     * */
    private Map<String, Class<?>> getTypes = new HashMap<>();
    // 默认构造函数
    private Constructor<?> defaultConstructor;
    /**
     * 用于保存大写属性名与属性名之间的映射,比如 <NAME, name>
     * */
    private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();

    // 解析所有的属性和方法并把数据处理到全局变量里
    public Reflector(Class<?> clazz) {
        this.type = clazz;
        // 加入构造函数
        addDefaultConstructor(clazz);
        // 反射解析getter方法加入 getterMethods
        addGetMethods(clazz);
        // 反射解析setter方法加入 setterMethods 
        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) {
            caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
        }
        for (String propName : writeablePropertyNames) {
            caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
        }
    }

    private void addDefaultConstructor(Class<?> clazz) {
        Constructor<?>[] consts = clazz.getDeclaredConstructors();
        for (Constructor<?> constructor : consts) {
            if (constructor.getParameterTypes().length == 0) {
                if (canAccessPrivateMethods()) {
                    try {
                        constructor.setAccessible(true);
                    } catch (Exception ignore) {
                        // Ignored. This is only a final precaution, nothing we can do
                    }
                }
                if (constructor.isAccessible()) {
                    this.defaultConstructor = constructor;
                }
            }
        }
    }

    private void addGetMethods(Class<?> clazz) {
        Map<String, List<Method>> conflictingGetters = new HashMap<>();
        // 获取类中的方法
        Method[] methods = getClassMethods(clazz);
        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);
    }

    private void addSetMethods(Class<?> clazz) {
        Map<String, List<Method>> conflictingSetters = new HashMap<>();
        Method[] methods = getClassMethods(clazz);
        for (Method method : methods) {
            String name = method.getName();
            if (name.startsWith("set") && name.length() > 3) {
                if (method.getParameterTypes().length == 1) {
                    name = PropertyNamer.methodToProperty(name);
                    addMethodConflict(conflictingSetters, name, method);
                }
            }
        }
        resolveSetterConflicts(conflictingSetters);
    }

    private void resolveSetterConflicts(Map<String, List<Method>> conflictingSetters) {
        for (String propName : conflictingSetters.keySet()) {
            List<Method> setters = conflictingSetters.get(propName);
            Method firstMethod = setters.get(0);
            if (setters.size() == 1) {
                addSetMethod(propName, firstMethod);
            } else {
                Class<?> expectedType = getTypes.get(propName);
                if (expectedType == null) {
                    throw new RuntimeException("Illegal overloaded setter method with ambiguous type for property "
                            + propName + " in class " + firstMethod.getDeclaringClass() + ".  This breaks the JavaBeans " +
                            "specification and can cause unpredicatble results.");
                } else {
                    Iterator<Method> methods = setters.iterator();
                    Method setter = null;
                    while (methods.hasNext()) {
                        Method method = methods.next();
                        if (method.getParameterTypes().length == 1
                                && expectedType.equals(method.getParameterTypes()[0])) {
                            setter = method;
                            break;
                        }
                    }
                    if (setter == null) {
                        throw new RuntimeException("Illegal overloaded setter method with ambiguous type for property "
                                + propName + " in class " + firstMethod.getDeclaringClass() + ".  This breaks the JavaBeans " +
                                "specification and can cause unpredicatble results.");
                    }
                    addSetMethod(propName, setter);
                }
            }
        }
    }

    // 加入set方法以MethodInvoker放入全局变量里
    private void addSetMethod(String name, Method method) {
        if (isValidPropertyName(name)) {
            setMethods.put(name, new MethodInvoker(method));
            setTypes.put(name, method.getParameterTypes()[0]);
        }
    }

    private void addFields(Class<?> clazz) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (canAccessPrivateMethods()) {
                try {
                    field.setAccessible(true);
                } catch (Exception e) {
                    // Ignored. This is only a final precaution, nothing we can do.
                }
            }
            if (field.isAccessible()) {
                if (!setMethods.containsKey(field.getName())) {
                    // issue #379 - removed the check for final because JDK 1.5 allows
                    // modification of final fields through reflection (JSR-133). (JGB)
                    // pr #16 - final static can only be set by the classloader
                    int modifiers = field.getModifiers();
                    if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) {
                        addSetField(field);
                    }
                }
                if (!getMethods.containsKey(field.getName())) {
                    addGetField(field);
                }
            }
        }
        if (clazz.getSuperclass() != null) {
            addFields(clazz.getSuperclass());
        }
    }

    private void addSetField(Field field) {
        if (isValidPropertyName(field.getName())) {
            setMethods.put(field.getName(), new SetFieldInvoker(field));
            setTypes.put(field.getName(), field.getType());
        }
    }

    private void addGetField(Field field) {
        if (isValidPropertyName(field.getName())) {
            getMethods.put(field.getName(), new GetFieldInvoker(field));
            getTypes.put(field.getName(), field.getType());
        }
    }

    private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
        for (String propName : conflictingGetters.keySet()) {
            List<Method> getters = conflictingGetters.get(propName);
            Iterator<Method> iterator = getters.iterator();
            Method firstMethod = iterator.next();
            if (getters.size() == 1) {
                // 存放全局变量里
                addGetMethod(propName, firstMethod);
            } else {
                // 多个方法情况
                Method getter = firstMethod;
                Class<?> getterType = firstMethod.getReturnType();
                while (iterator.hasNext()) {
                    Method method = iterator.next();
                    Class<?> methodType = method.getReturnType();
                    if (methodType.equals(getterType)) {
                        throw new RuntimeException("Illegal overloaded getter method with ambiguous type for property "
                                + propName + " in class " + firstMethod.getDeclaringClass()
                                + ".  This breaks the JavaBeans " + "specification and can cause unpredicatble results.");
                    } else if (methodType.isAssignableFrom(getterType)) {
                        // OK getter type is descendant
                    } else if (getterType.isAssignableFrom(methodType)) {
                        getter = method;
                        getterType = methodType;
                    } else {
                        throw new RuntimeException("Illegal overloaded getter method with ambiguous type for property "
                                + propName + " in class " + firstMethod.getDeclaringClass()
                                + ".  This breaks the JavaBeans " + "specification and can cause unpredicatble results.");
                    }
                }
                addGetMethod(propName, getter);
            }
        }
    }

    // 加入get方法以MethodInvoker放入全局变量里
    private void addGetMethod(String name, Method method) {
        if (isValidPropertyName(name)) {
            getMethods.put(name, new MethodInvoker(method));
            getTypes.put(name, method.getReturnType());
        }
    }

    private boolean isValidPropertyName(String name) {
        return !(name.startsWith("$") || "serialVersionUID".equals(name) || "class".equals(name));
    }

    private void addMethodConflict(Map<String, List<Method>> conflictingMethods, String name, Method method) {
        List<Method> list = conflictingMethods.computeIfAbsent(name, k -> new ArrayList<>());
        list.add(method);
    }

    // 查找当前类及父类方法
    private Method[] getClassMethods(Class<?> cls) {
        Map<String, Method> uniqueMethods = new HashMap<String, Method>();
        Class<?> currentClass = cls;
        while (currentClass != null) {
            addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());

            // we also need to look for interface methods -
            // because the class may be abstract
            Class<?>[] interfaces = currentClass.getInterfaces();
            for (Class<?> anInterface : interfaces) {
                addUniqueMethods(uniqueMethods, anInterface.getMethods());
            }

            currentClass = currentClass.getSuperclass();
        }

        Collection<Method> methods = uniqueMethods.values();

        return methods.toArray(new Method[methods.size()]);
    }

    // 校验方法唯一性,暂存临时集合
    private void addUniqueMethods(Map<String, Method> uniqueMethods, Method[] methods) {
        for (Method currentMethod : methods) {
            if (!currentMethod.isBridge()) {
                //取得签名  方法返回值#方法名:方法参数(多个用逗号分割)
                String signature = getSignature(currentMethod);
                // check to see if the method is already known
                // if it is known, then an extended class must have
                // overridden a method
                if (!uniqueMethods.containsKey(signature)) {
                    if (canAccessPrivateMethods()) {
                        try {
                            currentMethod.setAccessible(true);
                        } catch (Exception e) {
                            // Ignored. This is only a final precaution, nothing we can do.
                        }
                    }

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

    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 static boolean canAccessPrivateMethods() {
        try {
            SecurityManager securityManager = System.getSecurityManager();
            if (null != securityManager) {
                securityManager.checkPermission(new ReflectPermission("suppressAccessChecks"));
            }
        } catch (SecurityException e) {
            return false;
        }
        return true;
    }


    public Class<?> getType() {
        return type;
    }

    // -------------------------------------------解析并存储的数据需要对外提供基础容器获取---------------
    public Constructor<?> getDefaultConstructor() {
        if (defaultConstructor != null) {
            return defaultConstructor;
        } else {
            throw new RuntimeException("There is no default constructor for " + type);
        }
    }

    public boolean hasDefaultConstructor() {
        return defaultConstructor != null;
    }

    public Class<?> getSetterType(String propertyName) {
        Class<?> clazz = setTypes.get(propertyName);
        if (clazz == null) {
            throw new RuntimeException("There is no setter for property named '" + propertyName + "' in '" + type + "'");
        }
        return clazz;
    }

    public Invoker getGetInvoker(String propertyName) {
        Invoker method = getMethods.get(propertyName);
        if (method == null) {
            throw new RuntimeException("There is no getter for property named '" + propertyName + "' in '" + type + "'");
        }
        return method;
    }

    public Invoker getSetInvoker(String propertyName) {
        Invoker method = setMethods.get(propertyName);
        if (method == null) {
            throw new RuntimeException("There is no setter for property named '" + propertyName + "' in '" + type + "'");
        }
        return method;
    }

    /*
     * Gets the type for a property getter
     *
     * @param propertyName - the name of the property
     * @return The Class of the propery getter
     */
    public Class<?> getGetterType(String propertyName) {
        Class<?> clazz = getTypes.get(propertyName);
        if (clazz == null) {
            throw new RuntimeException("There is no getter for property named '" + propertyName + "' in '" + type + "'");
        }
        return clazz;
    }

    /*
     * Gets an array of the readable properties for an object
     *
     * @return The array
     */
    public String[] getGetablePropertyNames() {
        return readablePropertyNames;
    }

    /*
     * Gets an array of the writeable properties for an object
     *
     * @return The array
     */
    public String[] getSetablePropertyNames() {
        return writeablePropertyNames;
    }

    /*
     * Check to see if a class has a writeable property by name
     *
     * @param propertyName - the name of the property to check
     * @return True if the object has a writeable property by the name
     */
    public boolean hasSetter(String propertyName) {
        return setMethods.keySet().contains(propertyName);
    }

    /*
     * Check to see if a class has a readable property by name
     *
     * @param propertyName - the name of the property to check
     * @return True if the object has a readable property by the name
     */
    public boolean hasGetter(String propertyName) {
        return getMethods.keySet().contains(propertyName);
    }

    public String findPropertyName(String name) {
        return caseInsensitivePropertyMap.get(name.toUpperCase(Locale.ENGLISH));
    }

    /*
     * Gets an instance of ClassInfo for the specified class.
     * 得到某个类的反射器,是静态方法,而且要缓存,又要多线程,所以REFLECTOR_MAP是一个ConcurrentHashMap
     *
     * @param clazz The class for which to lookup the method cache.
     * @return The method cache for the class
     */
    public static Reflector forClass(Class<?> clazz) {
        if (classCacheEnabled) {
            // synchronized (clazz) removed see issue #461
            // 对于每个类来说,我们假设它是不会变的,这样可以考虑将这个类的信息(构造函数,getter,setter,字段)加入缓存,以提高速度
            Reflector cached = REFLECTOR_MAP.get(clazz);
            if (cached == null) {
                cached = new Reflector(clazz);
                REFLECTOR_MAP.put(clazz, cached);
            }
            return cached;
        } else {
            return new Reflector(clazz);
        }
    }

    public static void setClassCacheEnabled(boolean classCacheEnabled) {
        Reflector.classCacheEnabled = classCacheEnabled;
    }

    public static boolean isClassCacheEnabled() {
        return classCacheEnabled;
    }

}

3.3 元类

MetaClass:元类,因为反射器都是基础的操作,为了方便使用对反射器的进一步封装,获取反射器里的容器数据,元类里提供反射器缓存,这样不用相同的类每次调用都解析处理了,也是补充丰富了反射器基础的操作,相当于解构一个对象包装一个元类,而这些元类,包装器,对象工厂再组合成一个元对象,相当于说这些元类和元对象都是对我们需要操作的原对象解耦后的封装。有了这样的操作,就可以让我们处理每一个属性或者方法了。

/**
 * @description 元类
 * Reflector 反射器类提供的是最基础的核心功能,很多方法也都是私有的,为了更加方便的使用,
 * 还需要做一层元类的包装。在元类 MetaClass 提供必要的创建反射器以及使用反射器获取
 * get/set 的 Invoker 反射方法
 * */
public class MetaClass {

    // 反射器,用于解析和存储目标类中的元信息
    private Reflector reflector;

    // Reflector.forClass获取当前类的反射器
    private MetaClass(Class<?> type) {
        this.reflector = Reflector.forClass(type);
    }

    public static MetaClass forClass(Class<?> type) {
        return new MetaClass(type);
    }

    public static boolean isClassCacheEnabled() {
        return Reflector.isClassCacheEnabled();
    }

    public static void setClassCacheEnabled(boolean classCacheEnabled) {
        Reflector.setClassCacheEnabled(classCacheEnabled);
    }

    public MetaClass metaClassForProperty(String name) {
        Class<?> propType = reflector.getGetterType(name);
        return MetaClass.forClass(propType);
    }

    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);
    }

    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 method.getGenericReturnType();
            } else if (invoker instanceof GetFieldInvoker) {
                Field _field = GetFieldInvoker.class.getDeclaredField("field");
                _field.setAccessible(true);
                Field field = (Field) _field.get(invoker);
                return field.getGenericType();
            }
        } catch (NoSuchFieldException | IllegalAccessException ignored) {
        }
        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);
    }

    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 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();
    }

}

3.4 对象包装器

ObjectWapper:对象包装器接口,定义对象基本操作,获取对象值、设置对象值、查找属性、获取get方法、获取set方法、属性类型、添加属性、设置属性等等...对象包装器主要是定义了更加明确的使用方法。

package df.middleware.mybatis.reflection.wrapper

/**
 * @description 对象包装器
 * 是对对象的包装的接口,抽象了对象的字段信息、 getter| setter 方法、和上面三个成员的数据类型,
 * 它定义了一系列查询对象属性信息的方法,以及更新属性的方法 。添加属性方法
 */
public interface ObjectWrapper {

    // get
    Object get(PropertyTokenizer prop);

    // set
    void set(PropertyTokenizer prop, Object value);

    // 查找属性
    String findProperty(String name, boolean useCamelCaseMapping);

    // 取得getter的名字列表
    String[] getGetterNames();

    // 取得setter的名字列表
    String[] getSetterNames();

    //取得setter的类型
    Class<?> getSetterType(String name);

    // 取得getter的类型
    Class<?> getGetterType(String name);

    // 是否有指定的setter
    boolean hasSetter(String name);

    // 是否有指定的getter
    boolean hasGetter(String name);

    // 实例化属性
    MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory);

    // 是否是集合
    boolean isCollection();

    // 添加属性
    void add(Object element);

    // 添加属性
    <E> void addAll(List<E> element);

}

BaseWrapper:基础对象包装器,抽象类,实现ObjectWapper,主要是抽取公共代码,方便由各子类对象包装器使用,如处理集合则可调用基础对象包装器方法即可,此类主要处理解析集合、获取集合、设置集合中的值

/**
 * @description 对象包装器抽象基类,提供一些工具方法
 * BaseWrapper 抽象类 定义了集合的相关操作。
 * 1.解析集合
 * 2.获取集合中的值
 * 3.设置集合中的值
 * */
public abstract class BaseWrapper implements ObjectWrapper {

    protected static final Object[] NO_ARGUMENTS = new Object[0];
    protected MetaObject metaObject;

    protected BaseWrapper(MetaObject metaObject) {
        this.metaObject = metaObject;
    }

    /**
     * 解析集合
     */
    protected Object resolveCollection(PropertyTokenizer prop, Object object) {
        if ("".equals(prop.getName())) {
            return object;
        } else {
            return metaObject.getValue(prop.getName());
        }
    }

    /**
     * 取集合的值
     * 中括号有2个意思,一个是Map,一个是List或数组
     */
    protected Object getCollectionValue(PropertyTokenizer prop, Object collection) {
        if (collection instanceof Map) {
            //map['name']
            return ((Map) collection).get(prop.getIndex());
        } else {
            int i = Integer.parseInt(prop.getIndex());
            if (collection instanceof List) {
                //list[0]
                return ((List) collection).get(i);
            } else if (collection instanceof Object[]) {
                return ((Object[]) collection)[i];
            } else if (collection instanceof char[]) {
                return ((char[]) collection)[i];
            } else if (collection instanceof boolean[]) {
                return ((boolean[]) collection)[i];
            } else if (collection instanceof byte[]) {
                return ((byte[]) collection)[i];
            } else if (collection instanceof double[]) {
                return ((double[]) collection)[i];
            } else if (collection instanceof float[]) {
                return ((float[]) collection)[i];
            } else if (collection instanceof int[]) {
                return ((int[]) collection)[i];
            } else if (collection instanceof long[]) {
                return ((long[]) collection)[i];
            } else if (collection instanceof short[]) {
                return ((short[]) collection)[i];
            } else {
                throw new RuntimeException("The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");
            }
        }
    }

    /**
     * 设集合的值
     * 中括号有2个意思,一个是Map,一个是List或数组
     */
    protected void setCollectionValue(PropertyTokenizer prop, Object collection, Object value) {
        if (collection instanceof Map) {
            ((Map) collection).put(prop.getIndex(), value);
        } else {
            int i = Integer.parseInt(prop.getIndex());
            if (collection instanceof List) {
                ((List) collection).set(i, value);
            } else if (collection instanceof Object[]) {
                ((Object[]) collection)[i] = value;
            } else if (collection instanceof char[]) {
                ((char[]) collection)[i] = (Character) value;
            } else if (collection instanceof boolean[]) {
                ((boolean[]) collection)[i] = (Boolean) value;
            } else if (collection instanceof byte[]) {
                ((byte[]) collection)[i] = (Byte) value;
            } else if (collection instanceof double[]) {
                ((double[]) collection)[i] = (Double) value;
            } else if (collection instanceof float[]) {
                ((float[]) collection)[i] = (Float) value;
            } else if (collection instanceof int[]) {
                ((int[]) collection)[i] = (Integer) value;
            } else if (collection instanceof long[]) {
                ((long[]) collection)[i] = (Long) value;
            } else if (collection instanceof short[]) {
                ((short[]) collection)[i] = (Short) value;
            } else {
                throw new RuntimeException("The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");
            }
        }
    }
}

MapWrapper:Map对象包装器,是对Map对象的封装,继承了 BaseWrapper,构造传入map类型对象,获取设置值等等也以map方式即可。

/**

 * @description Map 包装器
 * MapWrapper 是 Map 集合对象的封装。
*/
public class MapWrapper extends BaseWrapper {

    // 原来的对象
    private Map<String, Object> map;

    public MapWrapper(MetaObject metaObject, Map<String, Object> map) {
        super(metaObject);
        this.map = map;
    }

    // get,set是允许的,
    @Override
    public Object get(PropertyTokenizer prop) {
        //如果有index,说明是集合,那就要分解集合,调用的是BaseWrapper.resolveCollection 和 getCollectionValue
        if (prop.getIndex() != null) {
            Object collection = resolveCollection(prop, map);
            return getCollectionValue(prop, collection);
        } else {
            return map.get(prop.getName());
        }
    }

    @Override
    public void set(PropertyTokenizer prop, Object value) {
        if (prop.getIndex() != null) {
            Object collection = resolveCollection(prop, map);
            setCollectionValue(prop, collection, value);
        } else {
            map.put(prop.getName(), value);
        }
    }

    @Override
    public String findProperty(String name, boolean useCamelCaseMapping) {
        return name;
    }

    @Override
    public String[] getGetterNames() {
        return map.keySet().toArray(new String[map.keySet().size()]);
    }

    @Override
    public String[] getSetterNames() {
        return map.keySet().toArray(new String[map.keySet().size()]);
    }

    @Override
    public Class<?> getSetterType(String name) {
        PropertyTokenizer prop = new PropertyTokenizer(name);
        if (prop.hasNext()) {
            MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
            if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
                return Object.class;
            } else {
                return metaValue.getSetterType(prop.getChildren());
            }
        } else {
            if (map.get(name) != null) {
                return map.get(name).getClass();
            } else {
                return Object.class;
            }
        }
    }

    @Override
    public Class<?> getGetterType(String name) {
        PropertyTokenizer prop = new PropertyTokenizer(name);
        if (prop.hasNext()) {
            MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
            if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
                return Object.class;
            } else {
                return metaValue.getGetterType(prop.getChildren());
            }
        } else {
            if (map.get(name) != null) {
                return map.get(name).getClass();
            } else {
                return Object.class;
            }
        }
    }

    @Override
    public boolean hasSetter(String name) {
        return true;
    }

    @Override
    public boolean hasGetter(String name) {
        PropertyTokenizer prop = new PropertyTokenizer(name);
        if (prop.hasNext()) {
            if (map.containsKey(prop.getIndexedName())) {
                MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
                if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
                    return true;
                } else {
                    return metaValue.hasGetter(prop.getChildren());
                }
            } else {
                return false;
            }
        } else {
            return map.containsKey(prop.getName());
        }
    }

    @Override
    public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
        HashMap<String, Object> map = new HashMap<String, Object>();
        set(prop, map);
        return MetaObject.forObject(map, metaObject.getObjectFactory(), metaObject.getObjectWrapperFactory());
    }

    @Override
    public boolean isCollection() {
        return false;
    }

    @Override
    public void add(Object element) {
        throw new UnsupportedOperationException();
    }

    @Override
    public <E> void addAll(List<E> element) {
        throw new UnsupportedOperationException();
    }
}

CollectionWrapper:Collection对象包装器,实现ObjectWapper接口,除了添加集合、暂不支持其他操作,抛出异常即可。

/**
 * @author 小傅哥,微信:fustack
 * @description Collection 包装器
 */
public class CollectionWrapper implements ObjectWrapper{

    // 原来的对象
    private Collection<Object> object;

    public CollectionWrapper(MetaObject metaObject, Collection<Object> object) {
        this.object = object;
    }

    // get,set都是不允许的,只能添加元素
    @Override
    public Object get(PropertyTokenizer prop) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void set(PropertyTokenizer prop, Object value) {
        throw new UnsupportedOperationException();
    }

    @Override
    public String findProperty(String name, boolean useCamelCaseMapping) {
        throw new UnsupportedOperationException();
    }

    @Override
    public String[] getGetterNames() {
        throw new UnsupportedOperationException();
    }

    @Override
    public String[] getSetterNames() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Class<?> getSetterType(String name) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Class<?> getGetterType(String name) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean hasSetter(String name) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean hasGetter(String name) {
        throw new UnsupportedOperationException();
    }

    @Override
    public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean isCollection() {
        return true;
    }

    @Override
    public void add(Object element) {
        object.add(element);
    }

    @Override
    public <E> void addAll(List<E> element) {
        object.addAll(element);
    }

}

BeanWrapper:原始对象的封装,自定义对象封装,继承BaseWapper,这个是重点,因为是Bean对象,我们需要解析类里属性以及get,set方法,此时我们需要通过元类进入反射器进行解析,所以BeanWrapper依赖MetaClass

/**
 * @description Bean 包装器
 * BeanWrapper 是原始对象的封装
 */
public class BeanWrapper extends BaseWrapper {

    // 原来的对象
    private Object object;
    // 元类
    private MetaClass metaClass;

    public BeanWrapper(MetaObject metaObject, Object object) {
        super(metaObject);
        this.object = object;
        // 通过元类获取反射器 1个入口
        this.metaClass = MetaClass.forClass(object.getClass());
    }

    @Override
    public Object get(PropertyTokenizer prop) {
        // 如果有index(有中括号),说明是集合,那就要解析集合,调用的是 BaseWrapper.resolveCollection 和 getCollectionValue
        if (prop.getIndex() != null) {
            Object collection = resolveCollection(prop, object);
            return getCollectionValue(prop, collection);
        } else {
            // 否则,getBeanProperty
            return getBeanProperty(prop, object);
        }
    }

    @Override
    public void set(PropertyTokenizer prop, Object value) {
        // 如果有index,说明是集合,那就要解析集合,调用的是BaseWrapper.resolveCollection 和 setCollectionValue
        if (prop.getIndex() != null) {
            Object collection = resolveCollection(prop, object);
            setCollectionValue(prop, collection, value);
        } else {
            // 否则,setBeanProperty
            setBeanProperty(prop, object, value);
        }
    }

    @Override
    public String findProperty(String name, boolean useCamelCaseMapping) {
        return metaClass.findProperty(name, useCamelCaseMapping);
    }

    @Override
    public String[] getGetterNames() {
        return metaClass.getGetterNames();
    }

    @Override
    public String[] getSetterNames() {
        return  metaClass.getSetterNames();
    }

    @Override
    public Class<?> getSetterType(String name) {
        PropertyTokenizer prop = new PropertyTokenizer(name);
        if (prop.hasNext()) {
            MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
            if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
                return metaClass.getSetterType(name);
            } else {
                return metaValue.getSetterType(prop.getChildren());
            }
        } else {
            return metaClass.getSetterType(name);
        }
    }

    @Override
    public Class<?> getGetterType(String name) {
        PropertyTokenizer prop = new PropertyTokenizer(name);
        if (prop.hasNext()) {
            MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
            if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
                return metaClass.getGetterType(name);
            } else {
                return metaValue.getGetterType(prop.getChildren());
            }
        } else {
            return metaClass.getGetterType(name);
        }
    }

    @Override
    public boolean hasSetter(String name) {
        PropertyTokenizer prop = new PropertyTokenizer(name);
        if (prop.hasNext()) {
            if (metaClass.hasSetter(prop.getIndexedName())) {
                MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
                if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
                    return metaClass.hasSetter(name);
                } else {
                    return metaValue.hasSetter(prop.getChildren());
                }
            } else {
                return false;
            }
        } else {
            return metaClass.hasSetter(name);
        }
    }

    @Override
    public boolean hasGetter(String name) {
        PropertyTokenizer prop = new PropertyTokenizer(name);
        if (prop.hasNext()) {
            if (metaClass.hasGetter(prop.getIndexedName())) {
                MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
                if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
                    return metaClass.hasGetter(name);
                } else {
                    return metaValue.hasGetter(prop.getChildren());
                }
            } else {
                return false;
            }
        } else {
            return metaClass.hasGetter(name);
        }
    }

    @Override
    public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
        MetaObject metaValue;
        Class<?> type = getSetterType(prop.getName());
        try {
            Object newObject = objectFactory.create(type);
            metaValue = MetaObject.forObject(newObject, metaObject.getObjectFactory(), metaObject.getObjectWrapperFactory());
            set(prop, newObject);
        } catch (Exception e) {
            throw new RuntimeException("Cannot set value of property '" + name + "' because '" + name + "' is null and cannot be instantiated on instance of " + type.getName() + ". Cause:" + e.toString(), e);
        }
        return metaValue;
    }

    @Override
    public boolean isCollection() {
        return false;
    }

    @Override
    public void add(Object element) {
        throw new UnsupportedOperationException();
    }

    @Override
    public <E> void addAll(List<E> list) {
        throw new UnsupportedOperationException();
    }

    private Object getBeanProperty(PropertyTokenizer prop, Object object) {
        try {
            // 得到getter方法,然后调用
            Invoker method = metaClass.getGetInvoker(prop.getName());
            return method.invoke(object, NO_ARGUMENTS);
        } catch (RuntimeException e) {
            throw e;
        } catch (Throwable t) {
            throw new RuntimeException("Could not get property '" + prop.getName() + "' from " + object.getClass() + ".  Cause: " + t.toString(), t);
        }
    }

    private void setBeanProperty(PropertyTokenizer prop, Object object, Object value) {
        try {
            // 得到setter方法,然后调用
            Invoker method = metaClass.getSetInvoker(prop.getName());
            Object[] params = {value};
            method.invoke(object, params);
        } catch (Throwable t) {
            throw new RuntimeException("Could not set property '" + prop.getName() + "' of '" + object.getClass() + "' with value '" + value + "' Cause: " + t.toString(), t);
        }
    }
}

3.5 元对象

有了元类,反射器,对象包装器,最后我们统一一个元对象进行封装,对外统一调用方式,组成一个完整的元对象操作类。通过构造方法创建不同的对象包装器,获取此类中方法则自然调度到不同的wapper包装器里,实现整条链路

/**
 * @description 元对象
 * */
public class MetaObject {
    // 原对象
    private Object originalObject;
    /**
     * 封装过的 Object 对象
     */
    // 对象包装器
    private ObjectWrapper objectWrapper;
    // 对象工厂
    private ObjectFactory objectFactory;
    // 对象包装工厂
    private ObjectWrapperFactory objectWrapperFactory;

    // 赋值为不同的包装器
    private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory) {
        this.originalObject = object;
        this.objectFactory = objectFactory;
        this.objectWrapperFactory = objectWrapperFactory;

        if (object instanceof ObjectWrapper) {
            // 如果对象本身已经是ObjectWrapper型,则直接赋给objectWrapper
            this.objectWrapper = (ObjectWrapper) object;
        } else if (objectWrapperFactory.hasWrapperFor(object)) {
            // 如果有包装器,调用ObjectWrapperFactory.getWrapperFor
            this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
        } else if (object instanceof Map) {
            // 如果是Map型,返回MapWrapper
            this.objectWrapper = new MapWrapper(this, (Map) object);
        } else if (object instanceof Collection) {
            // 如果是Collection型,返回CollectionWrapper
            this.objectWrapper = new CollectionWrapper(this, (Collection) object);
        } else {
            // 除此以外,返回BeanWrapper
            this.objectWrapper = new BeanWrapper(this, object);
        }
    }

    /**
     * 创建 MetaObject 对象
     *
     * @param object 原始 Object 对象
     * @param objectFactory
     * @param objectWrapperFactory
     * @return MetaObject 对象
     */
    public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory) {
        if (object == null) {
            // 处理一下null,将null包装起来
            return SystemMetaObject.NULL_META_OBJECT;
        } else {
            return new MetaObject(object, objectFactory, objectWrapperFactory);
        }
    }

    public ObjectFactory getObjectFactory() {
        return objectFactory;
    }

    public ObjectWrapperFactory getObjectWrapperFactory() {
        return objectWrapperFactory;
    }

    public Object getOriginalObject() {
        return originalObject;
    }

    /* --------以下方法都是委派给 ObjectWrapper------ */
    // 查找属性,相当于又封装了一层
    public String findProperty(String propName, boolean useCamelCaseMapping) {
        return objectWrapper.findProperty(propName, useCamelCaseMapping);
    }

    /**
     * 获取get方法属性名称和get方法去掉get后边的属性名称
     * getIds(){return id;} --> (id、ids)
     * @return
     */
    // 取得getter的名字列表
    public String[] getGetterNames() {
        return objectWrapper.getGetterNames();
    }

    /**
     * 获取set方法属性名称和set方法去掉set后边的属性名称
     * setIds(){return id;} --> (id、ids)
     * @return
     */
    // 取得setter的名字列表
    public String[] getSetterNames() {
        return objectWrapper.getSetterNames();
    }

    /**
     * 获取set方法后边属性的类型
     * @param name 这个name 要和setXXX方法中的XXX相同才能获取到,否则抛异常
     * @return
     */
    // 取得setter的类型列表
    public Class<?> getSetterType(String name) {
        return objectWrapper.getSetterType(name);
    }

    /**
     * 获取get方法后边属性的类型
     * @param name 这个name,要个getXXX方法中的XXX相同才能获取到,否则抛异常
     * @return
     */
    // 取得getter的类型列表
    public Class<?> getGetterType(String name) {
        return objectWrapper.getGetterType(name);
    }

    /**
     * 判断name是否是setXXX()方法中的XXX
     * @param name
     * @return
     */
    //是否有指定的setter
    public boolean hasSetter(String name) {
        return objectWrapper.hasSetter(name);
    }

    /**
     * 判断name是否是getXXX()方法中的XXX
     * @param name
     * @return
     */
    // 是否有指定的getter
    public boolean hasGetter(String name) {
        return objectWrapper.hasGetter(name);
    }

    /**
     * 获取对象属性值,可以递归获取
     * @param name
     * @return
     */
    // 取得值
    // 如 班级[0].学生.成绩
    public Object getValue(String name) {
        // 创建 PropertyTokenizer 对象,对 name 分词
        PropertyTokenizer prop = new PropertyTokenizer(name);
        // 有子表达式
        if (prop.hasNext()) {
            // 创建 MetaObject 对象,递归调用
            MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
            // 递归判断子表达式 children ,获取值,metaValue == null,则返回null
            if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
                // 如果上层就是null了,那就结束,返回null
                return null;
            } else {
                // 否则继续看下一层,递归调用getValue
                return metaValue.getValue(prop.getChildren());
            }
        } else {
            // 无子表达式,取值
            return objectWrapper.get(prop);
        }
    }

    /**
     * 给对象属性设置值,可以递归设置,基本类型,数组,对象,都可以自动创建
     * 但是ArrayList和数组需要手动创建
     * List必须创建对象,添加进list
     * @param name
     * @param value
     */
    // 如 班级[0].学生.成绩
    public void setValue(String name, Object value) {
        // 创建 PropertyTokenizer 对象,对 name 分词
        PropertyTokenizer prop = new PropertyTokenizer(name);
        // 有子表达式
        if (prop.hasNext()) {
            // 创建 MetaObject 对象
            MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
            // 递归判断子表达式 children ,设置值
            if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
                if (value == null && prop.getChildren() != null) {
                    // don't instantiate child path if value is null
                    // 如果上层就是 null 了,还得看有没有儿子,没有那就结束
                    return;
                } else {
                    // 创建值
                    // 否则还得 new 一个,委派给 ObjectWrapper.instantiatePropertyValue
                    metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
                }
            }
            // 递归调用setValue
            metaValue.setValue(prop.getChildren(), value);
        } else {
            // 到了最后一层了,所以委派给 ObjectWrapper.set
            objectWrapper.set(prop, value);
        }
    }

    // 为属性生成元对象
    public MetaObject metaObjectForProperty(String name) {
        // 实际是递归调用
        Object value = getValue(name);
        return MetaObject.forObject(value, objectFactory, objectWrapperFactory);
    }

    public ObjectWrapper getObjectWrapper() {
        return objectWrapper;
    }

    // 是否是集合
    public boolean isCollection() {
        return objectWrapper.isCollection();
    }

    // 添加属性
    public void add(Object element) {
        objectWrapper.add(element);
    }

    // 添加属性
    public <E> void addAll(List<E> list) {
        objectWrapper.addAll(list);
    }

}

3.6 系统元对象

SystemMetaObject:可通过此类获取元对象

/**
 * @description 一些系统级别的元对象
 */
public class SystemMetaObject {

    public static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
    public static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
    public static final MetaObject NULL_META_OBJECT = MetaObject.forObject(NullObject.class, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);

    private SystemMetaObject() {
        // Prevent Instantiation of Static Class
    }

    /**
     * 空对象
     */
    private static class NullObject {
    }

    public static MetaObject forObject(Object object) {
        return MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
    }
}

3.7 对象工厂

ObjectFactory:对象工厂接口,创建对象处理

/**
 * @description 对象工厂接口
*/
public interface ObjectFactory {

    /**
     * Sets configuration properties.
     * 设置属性
     * @param properties configuration properties
     */
    void setProperties(Properties properties);

    /**
     * Creates a new object with default constructor.
     * 生产对象
     * @param type Object type
     * @return <T>
     */
    <T> T create(Class<T> type);

    /**
     * Creates a new object with the specified constructor and params.
     * 生产对象,使用明确的构造函数和构造函数参数
     * @param type Object type
     * @param constructorArgTypes Constructor argument types
     * @param constructorArgs Constructor argument values
     * @return <T>
     */
    <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);

    /**
     * Returns true if this object can have a set of other objects.
     * It's main purpose is to support non-java.util.Collection objects like Scala collections.
     * 返回这个对象是否是集合,为了支持 Scala collections
     *
     * @since 3.1.0
     * @param type Object type
     * @return whether it is a collection or not
     */
    <T> boolean isCollection(Class<T> type);
}

DefaultObjectFactory:默认对象工厂,实现对象工厂,对象实例化操作,在对象包装器中复杂场景有子集合对象时进行对象生成操作。

/**
 * @description 默认对象工厂,所有的对象都有工厂来生成
*/
public class DefaultObjectFactory implements ObjectFactory, Serializable {

    private static final long serialVersionUID = -8855120656740914948L;

    @Override
    public void setProperties(Properties properties) {
        // no props for default 默认无属性可设置
    }

    @Override
    public <T> T create(Class<T> type) {
        return create(type, null, null);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
        // 1. 解析接口
        Class<?> classToCreate = resolveInterface(type);
        // 2. 类实例化
        return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
    }

    private <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
        try {
            Constructor<T> constructor;
            //如果没有传入constructor,调用空构造函数,核心是调用Constructor.newInstance
            if (constructorArgTypes == null || constructorArgs == null) {
                // 能够得到私有的和公有的构造方法
                constructor = type.getDeclaredConstructor();
                if (!constructor.isAccessible()) {
                    // 方法获得的构造器需要先设置可访问,再实例化对象
                    constructor.setAccessible(true);
                }
                return constructor.newInstance();
            }
            // 如果传入constructor,调用传入的构造函数,核心是调用Constructor.newInstance
            constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()]));
            if (!constructor.isAccessible()) {
                constructor.setAccessible(true);
            }
            return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
        } catch (Exception e) {
            // 如果出错,包装一下,重新抛出自己的异常
            StringBuilder argTypes = new StringBuilder();
            if (constructorArgTypes != null) {
                for (Class<?> argType : constructorArgTypes) {
                    argTypes.append(argType.getSimpleName());
                    argTypes.append(",");
                }
            }
            StringBuilder argValues = new StringBuilder();
            if (constructorArgs != null) {
                for (Object argValue : constructorArgs) {
                    argValues.append(argValue);
                    argValues.append(",");
                }
            }
            throw new RuntimeException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
        }
    }

    @Override
    public <T> boolean isCollection(Class<T> type) {
        return Collection.class.isAssignableFrom(type);
    }

    /**
     * 解析接口,将 interface 转换为实际的 class 类
     */
    protected Class<?> resolveInterface(Class<?> type) {
        Class<?> classToCreate;
        if (type == List.class || type == Collection.class || type == Iterable.class) {
            // List|Collection|Iterable-->ArrayList
            classToCreate = ArrayList.class;
        } else if (type == Map.class) {
            // Map->HashMap
            classToCreate = HashMap.class;
        } else if (type == SortedSet.class) {
            // SortedSet->TreeSet
            classToCreate = TreeSet.class;
        } else if (type == Set.class) {
            // Set->HashSet
            classToCreate = HashSet.class;
        } else {
            // 除此以外,就用原来的类型
            classToCreate = type;
        }
        return classToCreate;
    }
}

3.8 属性命名器

/**
 * @description 属性命名器
 * namer 命名者
 */
public class PropertyNamer {

    private PropertyNamer() {
    }

    /**
     * 方法转换为属性
     */
    public static String methodToProperty(String name) {
        if (name.startsWith("is")) {
            name = name.substring(2);
        } else if (name.startsWith("get") || name.startsWith("set")) {
            name = name.substring(3);
        } else {
            throw new RuntimeException("Error parsing property name '" + name + "'.  Didn't start with 'is', 'get' or 'set'.");
        }

        /*
         * 如果只有1个字母,转换为小写
         * 如果大于1个字母,第二个字母非大写,转换为小写
         */
        if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
            name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
        }

        return name;
    }

    /**
     * 开头判断是否是get/set/is的方法
     */
    public static boolean isProperty(String name) {
        return name.startsWith("get") || name.startsWith("set") || name.startsWith("is");
    }

    /**
     * 是否为 getter
     */
    public static boolean isGetter(String name) {
        return name.startsWith("get") || name.startsWith("is");
    }

    /**
     * 是否为 setter
     */
    public static boolean isSetter(String name) {
        return name.startsWith("set");
    }
}

3.9 属性分解器

PropertyTokenizer:此类贯穿整个工具使用,主要是解析属性是不是只是简单属性还是复杂属性,如果有集合,需要解析下标,子集合名称等操作

/**
 * @description 属性分解标记
 * 可以解析处理简单属性以及list集合Map等等的数据
 * 亮点:可迭代,可以看看
 */
public class PropertyTokenizer implements Iterable<PropertyTokenizer>, Iterator<PropertyTokenizer> {

    // 例子:班级[0].学生.成绩
    // 班级,父表达式
    private String name;
    // 班级[0],带索引的表达式,由父表达式和下标组成
    private String indexedName;
    // 0 ,下标,该属性只对字段类型为map|list|array类型的字段有效,对于list和array类型的字段,index保存的是下标。
    private String index;
    // 学生.成绩,,子表达式:该属性只对嵌套表达式有效
    private String children;

    public PropertyTokenizer(String fullname) {
        // 班级[0].学生.成绩
        // 找这个点 .
        // 解析出parent表达式和children表达式
        int delim = fullname.indexOf('.');
        if (delim > -1) {
            name = fullname.substring(0, delim);//截取到parent表达式
            children = fullname.substring(delim + 1);//截取到children表达式
        } else {
            // 找不到.的话,取全部部分
            name = fullname;//fullname 即为parent表达式
            children = null;//无children
        }
        indexedName = name;
        // 把中括号里的数字给解析出来
        delim = name.indexOf('[');
        if (delim > -1) {//如果有下标
            index = name.substring(delim + 1, name.length() - 1);保存下标到index
            name = name.substring(0, delim);//3.截取出field name,
        }
    }

    public String getName() {
        return name;
    }

    public String getIndex() {
        return index;
    }

    public String getIndexedName() {
        return indexedName;
    }

    public String getChildren() {
        return children;
    }

    @Override
    public boolean hasNext() {
        return children != null;
    }

    // 取得下一个,非常简单,直接再通过儿子来new另外一个实例
    @Override
    public PropertyTokenizer next() {
        return new PropertyTokenizer(children);
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException("Remove is not supported, as it has no meaning in the context of properties.");
    }

    @Override
    public Iterator<PropertyTokenizer> iterator() {
        return this;
    }
}

3.10 使用反射器数据源属性设置

那我们先来把UnpooledDataSourceFactory的数据源属性进行设置

public class UnpooledDataSourceFactory implements DataSourceFactory {

    protected DataSource dataSource;

    public UnpooledDataSourceFactory() {
        this.dataSource = new UnpooledDataSource();
    }

    protected Properties pros;

    @Override
    public void setProperties(Properties props) {
        MetaObject metaObject = SystemMetaObject.forObject(dataSource);
        for (Object key : props.keySet()) {
            String propertyName = (String) key;
            if (metaObject.hasSetter(propertyName)) {
                String value = (String) props.get(propertyName);
                Object convertedValue = convertValue(metaObject, propertyName, value);
                metaObject.setValue(propertyName, convertedValue);
            }
        }
    }

    @Override
    public DataSource getDataSource() {
        return dataSource;
    }

    /**
     * 根据setter的类型,将配置文件中的值强转成相应的类型
     */
    private Object convertValue(MetaObject metaObject, String propertyName, String value) {
        Object convertedValue = value;
        Class<?> targetType = metaObject.getSetterType(propertyName);
        if (targetType == Integer.class || targetType == int.class) {
            convertedValue = Integer.valueOf(value);
        } else if (targetType == Long.class || targetType == long.class) {
            convertedValue = Long.valueOf(value);
        } else if (targetType == Boolean.class || targetType == boolean.class) {
            convertedValue = Boolean.valueOf(value);
        }
        return convertedValue;
    }
}

到此我们所有的类都介绍完毕了,我们用单元测试可以测试下,测试准备和上几节一样,可直接运行debug看下通过反射将DataSource的驱动 ,用户名,密码等反射设置进来

完事,本节所有的代码都已完全展现,大家想要源码可以去bugStack冲动栈,小傅哥那里

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/388759.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

@mixin与@include介绍

目录mixin与include介绍定义一个mixin使用mixin传递变量如何引入mixinmixin与include介绍 在Sass里面&#xff0c;我们经常会见到mixin与include。 其中 mixin允许定义一个可以在整个样式表中重复使用的样式 include就是将我们定义的mixin引入到文档中 定义一个mixin mixin…

【春招面经】视源股份前端一面

前言 本次主要记录一下视源股份CVTE前端一面 &#xff08;3.3下午4点15&#xff09; 文章目录前言本次主要记录一下视源股份CVTE前端一面 &#xff08;3.3下午4点15&#xff09;问题总结介绍一下项目的来源以及做这个项目的初衷一直监听滚动&#xff0c;有没有对性能产生影响&a…

大数据技术之——zeppelin数据清洗

一、zeppelin的安装zeppelin解压后进入到conf配置文件界面。修改zeppelin-site.xml[roothadoop02 conf]# cp zeppelin-site.xml.template zeppelin-site.xml[roothadoop02 conf]# vim zeppelin-site.xml将IP地址和端口号设置成自己的修改 zeppelin-env.shexport JAVA HOME/opt/…

Linux小黑板(10):信号

我们写在linux系统环境下写一个程序&#xff0c;唔&#xff0c;"它的功能是每隔1s向屏幕打印hello world。"这时&#xff0c;我们在键盘上按出"Ctrl C"后,进程会发生什么&#xff1f;&#xff1f;我们清晰地看到&#xff0c;进程已经在我们按出"Ctrl…

UML2——行为图

目录 一、前言 二、活动图 三、交互图 3.1 一般序列图 3.2 时间约束序列图 3.3 协作图 四、用例图 五、状态图 一、前言 UML 是由视图&#xff08;View&#xff09;、图&#xff08;Diagrams&#xff09;、模型元素&#xff08;Model elements&#xff09;和通用机制等几…

(图像分割)基于图论的归一化分割

解释&#xff1a;将图像映射成图&#xff0c;以图为研究对象&#xff0c;利用图的理论知识获得图像的分割。 下面介绍&#xff1a;图的基本理论&#xff0c;基于图论的归一化分割算法 一、图的基本理论 图G&#xff1d;&#xff08;V&#xff0c;E&#xff0c;&#xff09;&…

《管理世界》数据复现:国有资本参股如何影响民营企业?——基于债务融资视角的研究

摘要&#xff1a; 本文以债务融资为切入点&#xff0c;从“未阐明的规则”和“阐明的规则”两个层面探讨了国有资本参股的“反向混改”是否以及如何影响民营企业。研究发现&#xff1a;国有资本参股可以显著降低民营企业的债务融资成本&#xff0c;扩大债务融资规模。…

性能测试——LoadRunner: Controller的使用

Controller Controller是用来创建测试环境&#xff0c;执行在VUG中编写的测试脚本 可以直接点击Controller的快捷方式打开,也可以在VUG中打开 这里将虚拟用户数设置为3,比较适合自己的电脑性能 整个controller分为下面几个模块 这里先设置左下角的目标计划 设置初始化:双击…

PHP 8.1.14升级低版本openssl扩展的操作方法

问题背景&#xff1a; PHP8.1.4内嵌openssl源码编译出来的openssl库版本号是1.0.2.x系列&#xff0c;低版本的openssl扩展存在安全漏洞&#xff0c;需要将该扩展升级openssl 社区最新版本3.0.8 操作步骤&#xff1a; 安装最新版本的openssl wget https://github.com/openssl…

Java面试总结(四)

synchroize的实例、静态、代码块的锁对象 修饰实例方法 修饰静态方法 修饰代码块 1、修饰实例方法 &#xff08;锁当前对象实例&#xff09; 给当前对象实例加锁&#xff0c;进入同步代码前要获得 当前对象实例的锁 。 synchronized void method() {//业务代码 }2、修饰静…

在vue中如果computed属性是一个异步操作怎么办?

在计算属性中使用异步方法时&#xff0c;可以使用async/await来处理异步操作。由于计算属性是基于它们的依赖缓存的&#xff0c;所以我们需要使用一个返回Promise的异步方法来确保计算属性能够正常运行。 下面是一个简单的示例&#xff0c;演示如何在计算属性中使用异步方法&am…

P6入门:P6 Professional常用快捷键/热键

目录 一 引言 Primavera P6 专业版 Primavera P6 EPPM&#xff08;网络客户端&#xff09; Primavera P6 Alt 键 Primavera P6 功能键 一 引言 在 Oracle Primavera P6 中&#xff0c;有热键命令可以节省宝贵的时间。尤其是作为一个与 Primavera P6 长打交道人熟练掌握这…

苹果手机备份的文件在电脑什么地方 苹果备份文件怎么查看

在这个网络信息时代&#xff0c;为手机进行定期备份已经成为了家常便饭。在使用备份软件对苹果手机进行备份后&#xff0c;苹果手机备份的文件在什么地方&#xff0c;苹果备份文件怎么查看呢&#xff1f;本文就带大家来了解一下。 一、苹果手机备份的文件在电脑什么地方 大家…

数据库三大范式、BC范式、第四范式

目录第一范式&#xff08;1NF&#xff09;&#xff1a;原子性&#xff08;存储的数据应该具有“不可再分性”&#xff09;第二范式&#xff08;2NF&#xff09;&#xff1a;唯一性 (消除非主键部分依赖联合主键中的部分字段)&#xff08;一定要在第一范式已经满足的情况下&…

Python之flask基础

文章目录入门小案例及认识路由小总结配置文件路由系统路由支持正则cbv &#xff08;用的比较少&#xff09;模板渲染变量及循环请求响应pipreqs&#xff08;找当前项目依赖的包&#xff09;闪现&#xff08;flash&#xff09;请求扩展&#xff08;类似中间件&#xff09;猴子补…

【Redis】Redis集群之哨兵机制

【Redis】Redis集群之哨兵机制 文章目录【Redis】Redis集群之哨兵机制1. 哨兵的作用和原理1.1 哨兵的作用1.2 redis服务状态监控1.3 选举新master1.4 故障转移1.5 总结2. 搭建哨兵集群2.1 准备实例和配置2.2 启动2.3 测试3. RedisTemplate的哨兵模式1. 哨兵的作用和原理 1.1 哨…

1634_linux中把pdf拆分成独立的图片文件

全部学习汇总&#xff1a; GreyZhang/toolbox: 常用的工具使用查询&#xff0c;非教程&#xff0c;仅作为自我参考&#xff01; (github.com) 最近工作学习之中使用pdf的频次非常高&#xff0c;这种格式的通用性的确是不错。在目前的很多平台上都有很好用的软件。不过&#xff…

ios设备管理软件 2.16.9官网Mac/Windows下载电脑版功能介绍

imazing 2.16.9官网Mac/Windows下载电脑版是款针对苹果设备所打造的管理工具。iMazing为用户提供多种设备管理功能&#xff0c;每一位用户都能以自己的形式管理苹果设备。iMazing与苹果设备连接后&#xff0c;用户就可以轻松传输文件&#xff0c;浏览保存信息等。 应用介绍 i…

Zookeeper3.5.7版本——集群启动停止脚本

目录一、Zookeeper3.5.7集群部署&#xff08;linux环境-centos7&#xff09;二、3台服务器信息三、Zookeeper3.5.7集群启动停止脚本3.1、编写zk.sh脚本3.2、增加脚本执行权限3.3、执行Zookeeper 集群的zk.sh脚本四、执行脚本启动Zookeeper 集群五、执行脚本查看Zookeeper 集群状…

Lesson11---分类问题

11.1 逻辑回归 11.1.1 广义线性回归 课程回顾 线性回归&#xff1a;将自变量和因变量之间的关系&#xff0c;用线性模型来表示&#xff1b;根据已知的样本数据&#xff0c;对未来的、或者未知的数据进行估计 11.1.2 逻辑回归 11.1.2.1 分类问题 分类问题&#xff1a;垃圾…