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创建实例需要的参数类型列表和参数列表