一、简介
MyBatis使用 ObjectFactory
对象来创建所有需要创建的新对象,ObjectFactory
是一个接口,接口定义如下:
public interface ObjectFactory {
/**
* 设置配置的 Properties
*/
void setProperties(Properties properties);
/**
* 使用默认构造方法创建对象
*/
<T> T create(Class<T> type);
/**
* 使用特定的构造方法和参数创建对象
*/
<T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);
/**
* 判断类是否为集合
*/
<T> boolean isCollection(Class<T> type);
}
二、DefaultObjectFactory
DefaultObjectFactory
是该接口的默认实现类,也是唯一实现类。
1、create(Class<T> type) &
create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs)
【功能】根据 Constructor 创建类对应的对象。
【源码与注解】
@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)实例化对象
// we know types are assignable
return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
}
【解析】
(1)解析集合接口类型,获取其对应的常用的实现类,源码如下:
// 对于常见的集合接口,返回其对应常用的实现类
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;
}
(2)调用 #instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs)
生成实例化对象,源码如下:
<T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
try {
Constructor<T> constructor;
// (2.1)如果构造参数类型或者构造参数为空,则对象要通过默认构造方法来创建
if (constructorArgTypes == null || constructorArgs == null) {
constructor = type.getDeclaredConstructor();
if (!constructor.isAccessible()) {
constructor.setAccessible(true);
}
return constructor.newInstance();
}
// (2.2)根据构造参数类型获取对应构造方法并创建对象
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) {
// (2.3)拼接 argTypes,作为异常信息返回
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 ,
}
// (2.4)拼接 argValues,作为异常信息返回
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 ,
}
// (2.5)创建对象失败,抛出异常
throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
}
}
- (2.1)使用默认构造方法创建对象
- (2.2)使用含参构造方法创建对象
- (2.3)拼接传入的构造参数类型,放在异常信息中返回
- (2.4)拼接传入的构造参数值,放在异常信息中返回
- (2.5)创建对象失败,抛出异常
2、isCollection(Class<T> type)
【功能】判断是否为集合类型
【源码与注解】
@Override
public <T> boolean isCollection(Class<T> type) {
return Collection.class.isAssignableFrom(type);
}
网友评论