<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
每个setting元素设置的详细描述,大家可以去官网中mybatis - Mybatis3 | 配置 设置(settings)直接学习了解:
3. 节点settings源码
private void parseConfiguration(XNode root) {
try {
propertiesElement(root.evalNode("properties"));
//解析节点
Properties settings = settingsAsProperties(root.evalNode("settings"));
//解析后settings配置作为参数传入loadCustomVfs方法
loadCustomVfs(settings);
//解析后settings配置作为参数传入loadCustomLogImpl方法
loadCustomLogImpl(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
//解析后settings配置作为参数传入settingsElement方法
settingsElement(settings);
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
通过上面源码我们,大概了解了settings节点的解析过程:先加载整个settings的元素到集合Properties中,然后再把带着Properties集合传递到具体的方法中,进行具体的处理,那整个源码具体详细的解析过程是什么样子的呢?
接下来我们将按照上面settings解析过程,深入到源码方法中去窥探。
private Properties settingsAsProperties(XNode context) {
//如果mybatis-config.xml没有配置节点,则返回一个空的Properties配置类集合
if (context == null) {
return new Properties();
}
//getChildrenAsProperties方法在XNode类中,下面的XNode类中该方法的源码,我们可以了解一下
// 把节点中的所有元素的name和value属性值已K-V形式设置到Properties配置类中
Properties props = context.getChildrenAsProperties();
// Check that all settings are known to the configuration class
// 直接翻译上面源码的因为注释:检查全局配置类Configuration是否知道所有settings设置
// MetaClass类中作用就是把Configuration的所有属性的命名封装为起来
// 然后对元素中的name进行遍历判断是否非Configuration全局配置类中的属性名称,存在非法的属性名称进行异常抛出
MetaClass metaConfig = MetaClass.forClass(Configuration.class, localReflectorFactory);
//遍历所有元素解析后name属性值,既Properties props中的Key
for (Object key : props.keySet()) {
//判断key是否存在,不存在则抛出BuilderException异常
//这里提醒一下大家,如果你启动mybatis出现下面的异常msg,可以直接就定位到settings节点中某个元素setting的name属性值配置错误了
if (!metaConfig.hasSetter(String.valueOf(key))) {
throw new BuilderException("The setting " + key + " is not known. Make sure you spelled it correctly (case sensitive).");
}
}
return props;
}
XNode类中getChildrenAsProperties() 方法源码
public Properties getChildrenAsProperties() {
Properties properties = new Properties();
//遍历节点的元素
for (XNode child : getChildren()) {
//获取元素的name属性的字符串值
String name = child.getStringAttribute("name");
//获取元素的value属性的字符串值
String value = child.getStringAttribute("value");
if (name != null && value != null) {
//name属性值作为key,value属性值作为value,存放到Properties集合中
properties.setProperty(name, value);
}
}
return properties;
}
Configuration类中的属性名称,与上面官网截图的设置名一一对应,以后我们有机会将单独对Configuration类进行源码分析介绍
private void loadCustomVfs(Properties props) throws ClassNotFoundException {
//获取元素中name属性为vfsImpl的value值
String value = props.getProperty("vfsImpl");
if (value != null) {
//自定义VFS的实现的类全限定名,以逗号分隔
String[] clazzes = value.split(",");
for (String clazz : clazzes) {
if (!clazz.isEmpty()) {
//利用反射获取VFS实现类的Class对象
@SuppressWarnings("unchecked")
Class<? extends VFS> vfsImpl = (Class<? extends VFS>)Resources.classForName(clazz);
//最后注册到全局配置类Configuration中的vfsImpl容器中
configuration.setVfsImpl(vfsImpl);
}
}
}
}
private void loadCustomLogImpl(Properties props) {
Class<? extends Log> logImpl = resolveClass(props.getProperty("logImpl"));
//最后注册到全局配置类Configuration中的logImpl容器中
configuration.setLogImpl(logImpl);
}
private void settingsElement(Properties props) {
configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL")));
configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE")));
configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));
configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory")));
configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));
configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), false));
configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));
configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true));
configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false));
configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE")));
configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null));
configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null));
configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false));
configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false));
configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION")));
configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER")));
configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString"));
configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true));
configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage")));
configuration.setDefaultEnumTypeHandler(resolveClass(props.getProperty("defaultEnumTypeHandler")));
configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false));
configuration.setUseActualParamName(booleanValueOf(props.getProperty("useActualParamName"), true));
configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));
configuration.setLogPrefix(props.getProperty("logPrefix"));
configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory")));
}