设计模式无处不在,在分析Mybatis加载Configuration的过程中,发现Mybatis使用了多种的设计模式。
工厂模式
下面的例子准确的来说是一个抽象工厂!
Configuration中有个属性:
protected ObjectFactory objectFactory = new DefaultObjectFactory();
Mybatis使用这个工厂去创建所有需要被创建的对象。
/**
* MyBatis uses an ObjectFactory to create all needed new Objects.
*
* @author Clinton Begin
*/
其最主要的一个方法,也就是俗称的工厂方法:
/**
* 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);
这个方法主要是根据Class对象去创建实例,可以肯定这个方法的实现需要使用java的反射机制。
再看这个方法的默认实现:
public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
Class<?> classToCreate = resolveInterface(type);
@SuppressWarnings("unchecked")
// we know types are assignable
T created = (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
return created;
}
private <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();
}
//带参的构造方法
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(String.valueOf(argValue));
argValues.append(",");
}
}
throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
}
}
我们完全可以实现一个ObjectFactory,通过如下配置让Mybatis使用自定义的ObjectFacotry
<!-- mybatis-config.xml -->
<objectFactory type="com.ashan.mybatis.AshanObjectFactory">
<property name="myProperty" value="myvalue"/>
</objectFactory>
构建者(Builder)模式
还记得XMLMapperBuilder的助手MapperBuilderAssisant吗?他就是使用构建者模式来创建ResultMap/ResultMapping/MappedStatement/Cache对象的,应该说是这个类提供了构建者模式给MapperBuilderAssisant使用。如ResultMapp.Builder:
public Re