org.apache.ibatis.reflection.factory.ObjectFactory
Mybatis中很多模块都会使用到ObjectFactory接口,该接口提供了多个create()方法的重载,通过这些create()方法可以创建指定类型的对象。代码和类图如下:
/** * MyBatis uses an ObjectFactory to create all needed new Objects. * MyBatis使用ObjectFactory创建所有需要的新对象 * @author Clinton Begin */ 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 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 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. * 检测指定类型是否为集合类型,主要处理java.util.Collection及其子类 * @param type Object type * @return whether it is a collection or not * @since 3.1.0 */ <T> boolean isCollection(Class<T> type); } 复制代码
org.apache.ibatis.reflection.factory.DefaultObjectFactory
是ObjectFactory的默认实现,代码比较简单看下注释就懂了,如下:
/** * @author Clinton Begin */ public class DefaultObjectFactory implements ObjectFactory, Serializable { private static final long serialVersionUID = -8855120656740914948L; /** * 通过无参构造器创建指定类的对象 */ @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) { Class<?> classToCreate = resolveInterface(type); // we know types are assignable return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs); } @Override public void setProperties(Properties properties) { // no props for default } /** * 根据参数列表,从指定类型中选择合适的构造器创建对象 * @param type 创建类的类型 * @param constructorArgTypes 指定构造器的参数类型列表 * @param constructorArgs 构造器参数列表 * @return */ private <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) { try { Constructor<T> constructor; // 没有constructorArgTypes和constructorArgs 则用默认无参构造器创建对象 if (constructorArgTypes == null || constructorArgs == null) { constructor = type.getDeclaredConstructor(); try { return constructor.newInstance(); } catch (IllegalAccessException e) { if (Reflector.canControlMemberAccessible()) { constructor.setAccessible(true); return constructor.newInstance(); } else { throw e; } } } // 根据指定构造器参数类型列表 找到指定构造器 创建对应对象 constructor = type .getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()])); try { return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()])); } catch (IllegalAccessException e) { if (Reflector.canControlMemberAccessible()) { constructor.setAccessible(true); return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()])); } else { throw e; } } } 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); } } /** * 对于创建常用的集合接口,返回指定的默认实现 * List、Collection、Iterable 返回ArrayList * Map 返回HashMap * SortedSet 返回TreeSet * Set 返回HashSet * @param type * @return */ 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; } /** * 判断类是否为集合类 * isAssignableFrom Reflector类里面有介绍啦,主要针对Class为主体的判断 */ @Override public <T> boolean isCollection(Class<T> type) { return Collection.class.isAssignableFrom(type); } } 复制代码
以下内容摘录自 Mybatis官网中文文档
MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。 如果想覆盖对象工厂的默认行为,则可以通过创建自己的对象工厂来实现。比如:
// ExampleObjectFactory.java public class ExampleObjectFactory extends DefaultObjectFactory { public Object create(Class type) { return super.create(type); } public Object create(Class type, List<Class> constructorArgTypes, List<Object> constructorArgs) { return super.create(type, constructorArgTypes, constructorArgs); } public void setProperties(Properties properties) { super.setProperties(properties); } public <T> boolean isCollection(Class<T> type) { return Collection.class.isAssignableFrom(type); } } 复制代码
<!-- mybatis-config.xml --> <objectFactory type="org.mybatis.example.ExampleObjectFactory"> <property name="someProperty" value="100"/> </objectFactory> 复制代码
ObjectFactory 接口很简单,它包含两个创建用的方法,一个是处理默认构造方法的,另外一个是处理带参数的构造方法的。 最后,setProperties方法可以被用来配置 ObjectFactory,在初始化你的ObjectFactory实例后,objectFactory元素体中定义的属性会被传递给 setProperties 方法。
本节内容比较简单主要就是利用反射去创建对象。但是有个小的知识点大家可以学习下
在Mybatis代码中有很多List转数组转的地方,以DefaultObjectFactory代码为例:
type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()])); 复制代码
像阿甘最开始的时候也没有太注意这一块,经常是直接给了一个长度为0的数组,发现也可以正常工作。如:
list.toArray(new String[0]); 复制代码
在实际的转换中除了指定数组类型,最好能加上数组长度。
为什么呢?可以先看下ArrayList的实现
// ArrayList.java @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { if (a.length < size) // Make a new array of a's runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } //Arrays.java public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) { @SuppressWarnings("unchecked") T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; } 复制代码
可以看到当初始化数组指定的长度小于要转化的List的长度,则会利用反射创建一个新的数组,再进行System.arraycopy操作,而指定了长度的初始化数组则会直接进行System.arraycopy操作。对性能的提升显而易见啦