Mybatis初始化流程(一)
阿新 • • 發佈:2021-08-11
Mybatis初始化流程,其實就是組裝重量級All-In-One物件Configuration的過程,主要分為系統環境引數初始化和Mapper對映初始化,其中Mapper對映初始化尤為重要。
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物件。
流程進入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進行逐一讀取。
<?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……
<typeAliases>元素:TypeAliasRegistry typeAliasRegistry。
<typeHandlers>元素:TypeHandlerRegistry typeHandlerRegistry。
<environments>元素:Environment environment。配置多個<environment>元素時,Mybatis只會讀取預設的那一個。
<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的內部資料結構,我做了一個對照圖。
這些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對映初始化,簡單的兩個步驟就完成了,過程並不複雜。