02 Mybatis源码篇---XML配置之properties 属性和settings 设置

时间:2022-08-08 00:03:21
     之前大概介绍了一下怎么使用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 ;
}

     通过源码的学习,跟深刻的理解了properties属性设置的优先级。优先级自高向低顺序是,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的是 properties 属性中指定的属性。


settings:

解析MyBatis配置文件configuration节点及子节点时:

/**
 * 解析MyBatis配置文件settings的设置
 */
Properties settings = settingsAsProperties(root.evalNode( "settings")) ;
/**
 * 指定VFS的实现
 */
loadCustomVfs(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的Settings设置,如果有哪些属性不明白,请参考“02 Mybatis应用篇---XML配置之properties 属性和settings 设置”或者参考官方文档。