Mybatis3.3.x技術內幕(八):Mybatis初始化流程(上)

Mybatis初始化流程,其實就是組裝重量級All-In-One對象Configuration的過程,主要分爲系統環境參數初始化和Mapper映射初始化,其中Mapper映射初始化尤其重要。
java

inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      return new DefaultSqlSessionFactory(parser.parse());
}

parser.parse()方法,已經返回了組裝完畢的Configuration對象。sql

流程進入XMLConfigBuilder.parse()方法。數據庫

public Configuration parse() {
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
  }

  private void parseConfiguration(XNode root) {
    try {
      Properties settings = settingsAsPropertiess(root.evalNode("settings"));
      propertiesElement(root.evalNode("properties"));
      loadCustomVfs(settings);
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      reflectionFactoryElement(root.evalNode("reflectionFactory"));
      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);
    }
  }

以上代碼,對mybatis-config.xml配置文件內的元素,使用XPath進行逐一讀取。
apache

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<properties resource="jdbc.properties">
		<property name="username" value="root" />
		<property name="password" value="123" />
	</properties>
	<settings>
		<setting name="localCacheScope" value="STATEMENT"/>
		<setting name="cacheEnabled" value="false" />
		<setting name="lazyLoadingEnabled" value="true" />
		<setting name="multipleResultSetsEnabled" value="true" />
		<setting name="useColumnLabel" value="true" />
		<setting name="useGeneratedKeys" value="false" />
		<setting name="defaultExecutorType" value="REUSE" />
		<setting name="defaultStatementTimeout" value="25000" />
	</settings>
	<typeAliases>
		<typeAlias alias="Student" type="com.mybatis3.domain.Student" />
		<typeAlias alias="Teacher" type="com.mybatis3.domain.Teacher" />
	</typeAliases>
	<typeHandlers>
		<typeHandler handler="com.mybatis3.typehandlers.PhoneTypeHandler" />
	</typeHandlers>
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="${driver}" />
				<property name="url" value="${url}" />
				<property name="username" value="${username}" />
				<property name="password" value="${password}" />
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<mapper resource="com/mybatis3/mappers/StudentMapper.xml" />
		<mapper resource="com/mybatis3/mappers/TeacherMapper.xml" />
	</mappers>
</configuration>

Xml文件元素和Configuration屬性映射表:網絡

<properties>元素:Properties variables數據結構

<settings>元素:Integer defaultStatementTimeout、Integer defaultFetchSize、ExecutorType defaultExecutorType……mybatis

<typeAliases>元素:TypeAliasRegistry typeAliasRegistryapp

<typeHandlers>元素:TypeHandlerRegistry typeHandlerRegistrydom

<environments>元素:Environment environment。配置多個<environment>元素時,Mybatis只會讀取默認的那一個。ide

<mappers>元素:MapperRegistry mapperRegistry


Mapper映射初始化是咱們關注的重點,即mapperElement(root.evalNode("mappers"))方法。

org.apache.ibatis.builder.xml.XMLMapperBuilder.parse()方法源碼。

  private void configurationElement(XNode context) {
    try {
      String namespace = context.getStringAttribute("namespace");
      if (namespace == null || namespace.equals("")) {
        throw new BuilderException("Mapper's namespace cannot be empty");
      }
      builderAssistant.setCurrentNamespace(namespace);
      cacheRefElement(context.evalNode("cache-ref"));
      cacheElement(context.evalNode("cache"));
      parameterMapElement(context.evalNodes("/mapper/parameterMap"));
      resultMapElements(context.evalNodes("/mapper/resultMap"));
      sqlElement(context.evalNodes("/mapper/sql"));
      buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);
    }
  }

逐一讀取Mapper.xml文件內的各個元素。爲了更爲直觀的瞭解xml元素至Mybatis的內部數據結構,我作了一個對照圖。


PS:我作的圖片,原本是很漂亮的,開源中國的博客系統,竟然把個人圖片壓縮的其醜無比,且模糊不清,你們湊合看吧。

這些Xml配置元素,Mybatis將它們分別封裝成了ParameterMap、ParameterMapping、ResultMap、ResultMapping、MappedStatement、BoundSql等內部數據結構對象。

這些數據庫結構對象,均放置於Configuration內部保存起來。

protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection");
protected final Map<String, ResultMap> resultMaps = new StrictMap<ResultMap>("Result Maps collection");
protected final Map<String, ParameterMap> parameterMaps = new StrictMap<ParameterMap>("Parameter Maps collection");


Mybatis初始化流程,通過系統環境參數初始化和Mapper映射初始化,簡單的兩個步驟就完成了,過程並不複雜。下一節,咱們將詳細講述初始化過程當中的一些細節。


版權提示:文章出自開源中國社區,若對文章感興趣,可關注個人開源中國社區博客(http://my.oschina.net/zudajun)。(通過網絡爬蟲或轉載的文章,常常丟失流程圖、時序圖,格式錯亂等,仍是看原版的比較好)

相關文章
相關標籤/搜索