之前大概介绍了一下怎么使用MyBatis的properties 属性和settings 设置。下面我主要跟踪一下源码,跟深层次的了解一下MyBatis的properties和settings。
properties:
前面我们了解,MyBatis有三种方式对properties的设置,并且他们的优先级自高向低的顺序依次是:通过方法参数传递,通过resource/url属性中指定的文件,最后通过properties属性中指定的属性。
下面我们跟踪源码,了解一下MyBatis设置properties的流程:
解析MyBatis配置文件configuration节点及子节点时,调用propertiesElement()来解析properties属性。
propertiesElement(root.evalNode(
"properties"))
;
看一下解析properties属性的源码:
private void propertiesElement(XNode context) throws Exception {
if (context != null) {
/**
* 解析properties 属性中指定的属性。
*/
Properties defaults = context.getChildrenAsProperties() ;
String resource = context.getStringAttribute( "resource") ; //resource 制定的属性路径
String url = context.getStringAttribute( "url") ; //url制定的属性路径
if (resource != null && url != null) {
throw new BuilderException( "The properties element cannot specify both a URL and a resource based property file reference. Please specify one or the other.") ;
}
/**
* 根据 properties 元素中的 resource 属性读取类路径下属性文件,并覆盖properties 属性中指定的同名属性。
*/
if (resource != null) {
defaults.putAll(Resources. getResourceAsProperties(resource)) ;
} else if (url != null) {
/**
* 根据properties元素中的url属性指定的路径读取属性文件,并覆盖properties 属性中指定的同名属性。
*/
defaults.putAll(Resources. getUrlAsProperties(url)) ;
}
/**
* 获取方法参数传递的properties
* 创建XMLConfigBuilder实例时,this.configuration.setVariables(props);
*/
Properties vars = configuration.getVariables() ;
if (vars != null) {
defaults.putAll(vars) ;
}
parser.setVariables(defaults) ;
configuration.setVariables(defaults) ;
}
}
解析MyBatis配置文件中,properties属性中指定的属性:
/**
* 解析MyBatis配置文件中的properties属性中指定的属性
* @return
*/
public Properties getChildrenAsProperties() {
Properties properties = new Properties() ;
for (XNode child : getChildren()) {
String name = child.getStringAttribute( "name") ;
String value = child.getStringAttribute( "value") ;
if (name != null && value != null) {
properties.setProperty(name , value) ;
}
}
return properties ;
}
* 解析MyBatis配置文件中的properties属性中指定的属性
* @return
*/
public Properties getChildrenAsProperties() {
Properties properties = new Properties() ;
for (XNode child : getChildren()) {
String name = child.getStringAttribute( "name") ;
String value = child.getStringAttribute( "value") ;
if (name != null && value != null) {
properties.setProperty(name , value) ;
}
}
return properties ;
}
通过源码的学习,跟深刻的理解了properties属性设置的优先级。优先级自高向低顺序是,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的是 properties 属性中指定的属性。
settings:
解析MyBatis配置文件configuration节点及子节点时:
/**
* 解析MyBatis配置文件settings的设置
*/
Properties settings = settingsAsProperties(root.evalNode( "settings")) ;
/**
* 指定VFS的实现
*/
loadCustomVfs(settings) ;
* 解析MyBatis配置文件settings的设置
*/
Properties settings = settingsAsProperties(root.evalNode( "settings")) ;
/**
* 指定VFS的实现
*/
loadCustomVfs(settings) ;
/**
* 根据MyBatis配置文件setting进行修改MyBatis的默认设置
*/
settingsElement(settings) ;
* 根据MyBatis配置文件setting进行修改MyBatis的默认设置
*/
settingsElement(settings) ;
/**
* 根据MyBatis配置文件setting进行修改MyBatis的默认设置
* @param props
* @throws Exception
*/
private void settingsElement(Properties props) throws Exception {
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.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")) ;
@SuppressWarnings( "unchecked")
Class<? extends Log> logImpl = (Class<? extends Log>)resolveClass(props.getProperty( "logImpl")) ;
configuration.setLogImpl(logImpl) ;
configuration.setConfigurationFactory(resolveClass(props.getProperty( "configurationFactory"))) ;
}
* 根据MyBatis配置文件setting进行修改MyBatis的默认设置
* @param props
* @throws Exception
*/
private void settingsElement(Properties props) throws Exception {
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.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")) ;
@SuppressWarnings( "unchecked")
Class<? extends Log> logImpl = (Class<? extends Log>)resolveClass(props.getProperty( "logImpl")) ;
configuration.setLogImpl(logImpl) ;
configuration.setConfigurationFactory(resolveClass(props.getProperty( "configurationFactory"))) ;
}
上面是MyBatis的Settings设置,如果有哪些属性不明白,请参考“02 Mybatis应用篇---XML配置之properties 属性和settings 设置”或者参考官方文档。