zoukankan      html  css  js  c++  java
  • Mybatis框架基础支持层——反射工具箱之对象工厂ObjectFactory&DefaultObjectFactory(5)

    ObjectFactory官方简介:MyBatis每次创建结果集对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。 如果想覆盖对象工厂的默认行为,则可以通过创建自己的对象工厂来实现。

    ObjectFactory接口源码:

    public interface ObjectFactory {
    
        /**
         * mybatis核心配置文件中自配置<objectFactory><property></property></objectFactory>
         * <p>
         * 中的property标签的内容,会在加载配置文件后,设置到Properties对象中
         */
        void setProperties(Properties properties);
    
        /**
         * 根据默认构造创建一个对象示例
         */
        <T> T create(Class<T> type);
    
        /**
         * 根据有参数构造,创建一个实例,
         * type:字节码对象Class
         * constructorArgTypes:构造方法中的各个参数类型
         * constructorArgs:构造方法中的各个参数值
         */
        <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);
    
        /**
         * 判断创建对象的字节码Class是否是集合类型
         */
        <T> boolean isCollection(Class<T> type);
    }

    DefaultObjectFactory源码分析:(mybatis提供的ObjectFactory唯一实现)

    /**
     * @author Clinton Begin
     */
    public class DefaultObjectFactory implements ObjectFactory, Serializable {
    
        private static final long serialVersionUID = -8855120656740914948L;
    
        /**
         * 默认构造方法调用有参构造,参数类型和参数都设为null
         */
        @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) {
            /**
             * resolveInterface方法根据字节码Class的类型返回该类型的一个具象化实例Class
             */
            Class<?> classToCreate = resolveInterface(type);
            // 类型是可以赋值的,返回一个初始化的实例对象
            return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
        }
    
        @Override
        public void setProperties(Properties properties) {
            // no props for default
        }
    
        /**
         * 给实例对象赋值
         */
        <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
            try {
                Constructor<T> constructor;
                /**
                 * 无参构造时,返回空的实例对象
                 */
                if (constructorArgTypes == null || constructorArgs == null) {
                    constructor = type.getDeclaredConstructor();
                    if (!constructor.isAccessible()) {
                        //如果构造方法是私有的,则设置可被访问到
                        constructor.setAccessible(true);
                    }
                    return constructor.newInstance();
                }
                /**
                 * 有参构造时,根据字节码Class和参数类型列表constructorArgTypes反射获取到有参数的构造方法Constructor
                 */
                constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()]));
                if (!constructor.isAccessible()) {
                    //如果构造方法是私有的,则设置可被访问到
                    constructor.setAccessible(true);
                }
                //最后用获得的构造方法对象constructor和参数列表constructorArgs反射获取到实例对象返回
                return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
            } catch (Exception e) {
                /**
                 * 整合参数类型列表和参数列表信息,以此抛出明确的异常信息
                 */
                StringBuilder argTypes = new StringBuilder();
                if (constructorArgTypes != null && !constructorArgTypes.isEmpty()) {
                    for (Class<?> argType : constructorArgTypes) {
                        argTypes.append(argType.getSimpleName());
                        argTypes.append(",");
                    }
                    argTypes.deleteCharAt(argTypes.length() - 1); // remove trailing ,
                }
                StringBuilder argValues = new StringBuilder();
                if (constructorArgs != null && !constructorArgs.isEmpty()) {
                    for (Object argValue : constructorArgs) {
                        argValues.append(String.valueOf(argValue));
                        argValues.append(",");
                    }
                    argValues.deleteCharAt(argValues.length() - 1); // remove trailing ,
                }
                throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
            }
        }
    
        protected Class<?> resolveInterface(Class<?> type) {
            Class<?> classToCreate;
            if (type == List.class || type == Collection.class || type == Iterable.class) {
                classToCreate = ArrayList.class;
            } else if (type == Map.class) {
                classToCreate = HashMap.class;
            } else if (type == SortedSet.class) { // issue #510 Collections Support
                classToCreate = TreeSet.class;
            } else if (type == Set.class) {
                classToCreate = HashSet.class;
            } else {
                classToCreate = type;
            }
            return classToCreate;
        }
    
        /**
         * 字节码Class是否是一个Collection
         */
        @Override
        public <T> boolean isCollection(Class<T> type) {
            return Collection.class.isAssignableFrom(type);
        }
    }

    说明默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。它不做其他任何的处理。如果我们想在创建实例化一个目标类的时候做点啥其他的动作,可以继承DefaultObjectFactory,覆写父类方法,并在mybatis-config.xml中注册配置这个对象工厂类。

    认知(知识有限,全靠想象,希望看官指正):

    ObjectFactory在Mybatis中的一个用处:

    我认为当在mapper文件中指定一条sql映射时,返回值类型就是用ObjectFactory要去创建的实例,并且sql查询出的结果集被解析为ObjectFactory创建实例需要的参数类型列表和参数列表

  • 相关阅读:
    O2O创业团队,遇到生死悠关的问题,希望大家支招?
    你所忽视的“办公室政治”
    Mac OS X下给树莓派安装Raspbian系统
    树莓派上的软件安装和卸载命令汇总
    树莓派实现PPPOE拨号上网
    VNC远程登录树莓派的图形界面 -- VNC Server安装与连接
    树莓派玩家必装的几个Android手机APP
    没有鼠标,没有键盘,没有显示器,没有网络,仅通过串口连接控制树莓派
    树莓派2代B型性能极限测试
    朋友分享的设计网站鉴赏 记录
  • 原文地址:https://www.cnblogs.com/wly1-6/p/10307661.html
Copyright © 2011-2022 走看看