SqlSessionFactoryBuilder中的build方法是入口
public SqlSessionFactory build(Reader reader, String environment, Properties properties) { try { //解析为dom文件,用于进一步解析 XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { reader.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } }
/** * 解析XML配置文件 * @return */ public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; // parser.evalNode("/configuration"):通过XPATH解析器,解析configuration根节点 // 从configuration根节点开始解析,最终将解析出的内容封装到Configuration对象中 parseConfiguration(parser.evalNode("/configuration")); return configuration; }
把配置中configuration进行解析:
private void parseConfiguration(XNode root) { try { //issue #117 read properties first // 解析</properties>标签 propertiesElement(root.evalNode("properties")); // 解析</settings>标签 Properties settings = settingsAsProperties(root.evalNode("settings")); loadCustomVfs(settings); loadCustomLogImpl(settings); // 解析</typeAliases>标签 typeAliasesElement(root.evalNode("typeAliases")); // 解析</plugins>标签 pluginElement(root.evalNode("plugins")); // 解析</objectFactory>标签 objectFactoryElement(root.evalNode("objectFactory")); // 解析</objectWrapperFactory>标签 objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); // 解析</reflectorFactory>标签 reflectorFactoryElement(root.evalNode("reflectorFactory")); settingsElement(settings); // read it after objectFactory and objectWrapperFactory issue #631 // 解析</environments>标签 environmentsElement(root.evalNode("environments")); // 解析</databaseIdProvider>标签 databaseIdProviderElement(root.evalNode("databaseIdProvider")); // 解析</typeHandlers>标签 typeHandlerElement(root.evalNode("typeHandlers")); // 解析</mappers>标签 mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } }
解析标签说明:
properties属性是用来引入外部properties配置文件的内容
settings是mybatis中的一些设置,比如一级二级缓存等。
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"))); }
typeAliases 是别名定义,如果直接配置的包,则进行反射拿到对应的类小写。
plugins 是指插件配置,比如需要进行拦截查询的,在查询前面进行输出sql语句。需要配置plugins。
objectFactory 是针对于反射的,当需要同意赋值当时候可以用的上。
ObjectWrapperFactory 指定的对象进行特殊的加工
reflectorFactory 是反射工具包
environments 配置一些环境变变量,可以配置多个数据源。
databaseIdProvider 定义多数据源支持
<!-- 定义多数据库支持-->
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql"/> <!--mysql的定义 -->
<property name="Oracle" value="oracle"/><!--oracle的定义 -->
<property name="SQL Server" value="sqlserver"/>
</databaseIdProvider>
typeHandlers 是类处理器,进行转换类型的。
mappers 是xml 的配置。
其中
mappers 会进行其他的解析:
/** * 解析<mappers>标签 * @param parent mappers标签对应的XNode对象 * @throws Exception */ private void mapperElement(XNode parent) throws Exception { if (parent != null) { // 获取<mappers>标签的子标签 for (XNode child : parent.getChildren()) { // <package>子标签 if ("package".equals(child.getName())) { // 获取mapper接口和mapper映射文件对应的package包名 String mapperPackage = child.getStringAttribute("name"); // 将包下所有的mapper接口以及它的代理对象存储到一个Map集合中,key为mapper接口类型,value为代理对象工厂 configuration.addMappers(mapperPackage); } else {// <mapper>子标签 // 获取<mapper>子标签的resource属性 String resource = child.getStringAttribute("resource"); // 获取<mapper>子标签的url属性 String url = child.getStringAttribute("url"); // 获取<mapper>子标签的class属性 String mapperClass = child.getStringAttribute("class"); // 它们是互斥的 if (resource != null && url == null && mapperClass == null) { ErrorContext.instance().resource(resource); InputStream inputStream = Resources.getResourceAsStream(resource); // 专门用来解析mapper映射文件 XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments()); // 通过XMLMapperBuilder解析mapper映射文件 mapperParser.parse(); } else if (resource == null && url != null && mapperClass == null) { ErrorContext.instance().resource(url); InputStream inputStream = Resources.getUrlAsStream(url); XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments()); // 通过XMLMapperBuilder解析mapper映射文件 mapperParser.parse(); } else if (resource == null && url == null && mapperClass != null) { Class<?> mapperInterface = Resources.classForName(mapperClass); // 将指定mapper接口以及它的代理对象存储到一个Map集合中,key为mapper接口类型,value为代理对象工厂 configuration.addMapper(mapperInterface); } else { throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one."); } } } } }