Mybatis源碼淺析(二)

前言

上一篇我們通過一個(gè)簡(jiǎn)單的例子了解了基于XML配置文件的方式初始化Mybatis的過程,毫不夸張的說,MyBatis初始化的過程,就是創(chuàng)建 Configuration對(duì)象的過程。而在構(gòu)建SqlSessionFactory的過程中,生成了XMLConfigBuilder實(shí)例對(duì)象,所以我們就先從XMLConfigBuilder說起。

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}

XMLConfigBuilder

首先我們先看下XMLConfigBuilder實(shí)例的創(chuàng)建過程,如上述所示,入?yún)閕nputStream,environment和properties, 如下所示,是通過生成XPathParser實(shí)例后調(diào)用私有構(gòu)造函數(shù)來生成的。XPathParser封裝了JDK中的Document和XPath對(duì)象,其實(shí)就是一個(gè)工具類,主要用來解析XML文件內(nèi)容的。

public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}

// 私有構(gòu)造函數(shù),對(duì)應(yīng)上面代碼中的this
private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
super(new Configuration());
ErrorContext.instance().resource("SQL Mapper Configuration");
this.configuration.setVariables(props);
this.parsed = false;
this.environment = environment;
this.parser = parser;
}

其實(shí)分析到這,Mybatis的初始化(其實(shí)就是創(chuàng)建Configuration實(shí)例的過程)過程就比較清晰了:

  1. 首先創(chuàng)建XMLConfigBuilder 實(shí)例,然后創(chuàng)建了 Configuration 實(shí)例,順便把解析XML文件內(nèi)容的工具類也創(chuàng)建好
  2. 在 XMLConfigBuilder 當(dāng)中解析 Configuration的每一個(gè)節(jié)點(diǎn),并設(shè)置到Configuration當(dāng)中去
  3. 最后返回 Configuration 實(shí)例,并以其為入殘參,來生成SqlSessionFactory實(shí)例
// 解析 Configuration的每一個(gè)節(jié)點(diǎn)
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);
}
}

BaseBuilder

XMLConfigBuilder繼承了 BaseBuilder,事實(shí)上,其他所有解析XML的Builder都繼承了這個(gè)類。下面是BaseBuilder的大致結(jié)構(gòu),由此看出,Configuration實(shí)例其實(shí)是存放在BaseBuilder中的。

public abstract class BaseBuilder {
protected final Configuration configuration;
protected final TypeAliasRegistry typeAliasRegistry;
protected final TypeHandlerRegistry typeHandlerRegistry;

public BaseBuilder(Configuration configuration) {
this.configuration = configuration;
this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();
this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry();
}
...... // 此處省略了很多方法
}

下圖是BaseBuilder的實(shí)現(xiàn)依賴圖,你會(huì)發(fā)現(xiàn),基本上所有解析XML的類都需要即成這個(gè)基類,其中的幾個(gè)類(Mapper相關(guān)的)以后會(huì)詳細(xì)描述。


_
_

XMLConfigBuilder 的具體工作

上問我們了解到,繼承了 BaseBuilder 的 XMLConfigBuilder, 其實(shí)是Myabtis初始化的真正入口,那 XMLConfigBuilder 實(shí)際上都做了些什么工作呢?其實(shí)都在 XMLConfigBuilder 實(shí)例的parse方法內(nèi)。

// parse方法
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}

從代碼上可以看出,其實(shí)parse()方法也是拋磚引玉的方法,真正干活的其實(shí)是 parseConfiguration 方法

private void parseConfiguration(XNode root) {
try {
Properties settings = settingsAsPropertiess(root.evalNode("settings"));
//issue #117 read properties first
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);
// read it after objectFactory and objectWrapperFactory issue #631
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 配置文件之解析詳解

從上面的 parseConfiguration 方法可以看出,Mybatis 配置文件中支持的節(jié)點(diǎn)類型包含如下內(nèi)容,先寫到這里,下篇文章依次來了解下每一項(xiàng)的解析過程.

  1. properties 屬性
  2. settings 設(shè)置
  3. typeAliases 類型命名
  4. plugins 插件
  5. objectFactory 對(duì)象工廠
  6. objectWrapperFactory
  7. reflectionFactory
  8. environments 環(huán)境
  9. databaseIdProvider 數(shù)據(jù)庫廠商標(biāo)識(shí)
  10. typeHandlers 類型處理器
  11. mappers 映射器
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 簡(jiǎn)介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲(chǔ)過程以及高級(jí)映射的優(yōu)秀的...
    笨鳥慢飛閱讀 6,238評(píng)論 0 4
  • 1 引言# 本文主要講解JDBC怎么演變到Mybatis的漸變過程,重點(diǎn)講解了為什么要將JDBC封裝成Mybait...
    七寸知架構(gòu)閱讀 77,557評(píng)論 36 979
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,562評(píng)論 19 139
  • 1. 準(zhǔn)備工作 為了看清楚MyBatis的整個(gè)初始化過程,先創(chuàng)建一個(gè)簡(jiǎn)單的Java項(xiàng)目,目錄結(jié)構(gòu)如下圖所示: 1....
    大閑人柴毛毛閱讀 16,697評(píng)論 3 34
  • 小莫兒: 今天看到一張圖,很有意思。 看到嗎,12歲青春期的女孩子,可愛指數(shù)開始直線下降,做媽媽的常常會(huì)感慨,“上...
    晶瑩晶瑩閱讀 657評(píng)論 1 2

友情鏈接更多精彩內(nèi)容