上一篇文章我们分析了标签typeAliases的解析,这篇文章我们接着分析下一个标签objectFactory的解析.
mybatis每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成,默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化.
我们可以在Configuration中看出,默认的对象工厂为:
protected ObjectFactory objectFactory = new DefaultObjectFactory();
我们也可以定义自己的对象工厂,如:
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
<property name="someProperty" value="100"/>
</objectFactory>
那接下来让我们看看代码中是怎么解析这个标签的,我们来看objectFactoryElement(root.evalNode(“objectFactory”));方法:
private void objectFactoryElement(XNode context) throws Exception {
if (context != null) {
// 获取objectFactory标签中的type属性值
String type = context.getStringAttribute("type");
// 获取objectFactory标签下所有子标签的name,value封装成Properties
Properties properties = context.getChildrenAsProperties();
// 实例化ObjectFactory工厂类,resolveClass方法是定义在BaseBuilder中,下面再进一步分析
ObjectFactory factory = (ObjectFactory) resolveClass(type).newInstance();
// 设置工厂参数
factory.setProperties(properties);
// 将自定义的objectFactory设置进Configuration中,从这里我们可以看出,我们自己实现的实例工厂类要实现ObjectFactory接口
configuration.setObjectFactory(factory);
}
}
分析(ObjectFactory) resolveClass(type).newInstance()方法:
// 该方法返回一个Class对象,newInstance()调用构造方法实例化对象.
protected Class<?> resolveClass(String alias) {
if (alias == null) return null;
try {
return resolveAlias(alias);
} catch (Exception e) {
throw new BuilderException("Error resolving class. Cause: " + e, e);
}
}
protected Class<?> resolveAlias(String alias) {
// typeAliasRegistry是不是似曾相识,这个属性就是存放别名的,所以可以看出,我们可以给自己的实例化工厂取别名,通过别名的方法去寻找它,那有的同学肯定也有疑惑,那我如果没有定义别名呢?我们接着看typeAliasRegistry的resolveAlias方法.
return typeAliasRegistry.resolveAlias(alias);
}
继续看typeAliasRegistry.resolveAlias(alias)方法:
// 上一篇文章中,我们说了别名的注册,其实这个方法,就是通过别名去获取Class类对象.还记得当时我们最终存储别名的时候,别名存储为小写吗?现在我们来验证一下,取值的时候是不是也是要转换成小写,再去取值.
public <T> Class<T> resolveAlias(String string) {
try {
if (string == null) return null;
// 果然,一开始就直接就别名转换成小写
String key = string.toLowerCase(Locale.ENGLISH);
Class<T> value;
if (TYPE_ALIASES.containsKey(key)) {
// 如果有相应的别名存储,则返回别名对应的Class值
value = (Class<T>) TYPE_ALIASES.get(key);
} else {
// 如果没有相应的别名存储,则通过Resources去加载这个类
value = (Class<T>) Resources.classForName(string);
}
return value;
} catch (ClassNotFoundException e) {
throw new TypeException("Could not resolve type alias '" + string + "'. Cause: " + e, e);
}
}
当我们要自定义实例化工厂时,实现的ObjectFactory接口也很简单,它包含两个创建用的方法.一个是处理默认构造方法的,另外一个是处理带参数的构造方法的. 最后,setProperties方法可以被用来配置ObjectFactor.在初始化你的ObjectFactory实例后,objectFactory元素体中定义的属性会被传递给setProperties方法,我们也在上述代码中看到了factory.setProperties(properties);.
至此,objectFactory就介绍完啦.