inputstream 初始化_MyBatis初始化之加载初始化
在MyBatis初始化過程中,大致會有以下幾個步驟:
1. 創(chuàng)建Configuration全局配置對象,會往TypeAliasRegistry別名注冊中心添加Mybatis需要用到的相關(guān)類,并設(shè)置默認(rèn)的語言驅(qū)動類為XMLLanguageDriver
2. 加載mybatis-config.xml配置文件、Mapper接口中的注解信息和XML映射文件,解析后的配置信息會形成相應(yīng)的對象并保存到Configuration全局配置對象中
3. 構(gòu)建DefaultSqlSessionFactory對象,通過它可以創(chuàng)建DefaultSqlSession對象,MyBatis中SqlSession的默認(rèn)實現(xiàn)類
因為整個初始化過程涉及到的代碼比較多,所以拆分成了四個模塊依次對MyBatis的初始化進行分析:
? 《MyBatis初始化(一)之加載mybatis-config.xml》
? 《MyBatis初始化(二)之加載Mapper接口與XML映射文件》
? 《MyBatis初始化(三)之SQL初始化(上)》
? 《MyBatis初始化(四)之SQL初始化(下)》
由于在MyBatis的初始化過程中去解析Mapper接口與XML映射文件涉及到的篇幅比較多,XML映射文件的解析過程也比較復(fù)雜,所以才分成了后面三個模塊,逐步分析,這樣便于理解
初始化(一)之加載mybatis-config.xml
本文主要分享的是在MyBatis初始化過程中,是如何加載mybatis-config.xml配置文件的,配置描述請參考:MyBatis官方文檔的配置說明
初始化入口在org.apache.ibatis.session.SqlSessionFactoryBuilder構(gòu)造器中,因為需要通過mybatis-config.xml配置文件構(gòu)建一個SqlSessionFactory工廠,用于創(chuàng)建SqlSession會話
主要涉及到以下幾個類:
? org.apache.ibatis.session.SqlSessionFactoryBuilder:用于構(gòu)建SqlSessionFactory工廠
? org.apache.ibatis.builder.xml.XMLConfigBuilder:根據(jù)配置文件進行解析,開始Mapper接口與XML映射文件的初始化,生成Configuration全局配置對象
? org.apache.ibatis.builder.xml.XMLMapperBuilder:繼承BaseBuilder抽象類,用于解析XML映射文件內(nèi)的標(biāo)簽
? org.apache.ibatis.session.Configuration:MyBatis的全局配置對象,保存所有的配置與初始化過程所產(chǎn)生的對象
SqlSessionFactoryBuilder
org.apache.ibatis.session.SqlSessionFactoryBuilder:構(gòu)建SqlSessionFactory工廠類,里面定義了許多build重載方法,主要分為處理Reader和InputStream兩種文件資源對象
我們來看看其中的一個build方法:
public class SqlSessionFactoryBuilder {
public SqlSessionFactory build(Reader reader) {
return build(reader, null, null);
}
/**
* 構(gòu)造 SqlSessionFactory 對象
*
* @param reader Reader 對象
* @param environment 環(huán)境
* @param properties Properties 變量
* @return SqlSessionFactory 對象
*/
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
/*
* <1> 創(chuàng)建 XMLConfigBuilder 對象
* 會生成一個 XPathParser,包含 Document 對象
* 會創(chuàng)建一個 Configuration 全局配置對象
*/
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
/*
* <2> 解析 XML 文件并配置到 Configuration 全局配置對象中
* <3> 創(chuàng)建 DefaultSqlSessionFactory 對象
*/
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.
}
}
}
}
build方法主要做了三件事:
1. 創(chuàng)建XMLConfigBuilder對象,生成XPathParser配置文件解析器對象和Configuration全局配置對象
2. 通過XMLConfigBuilder對象解析XML映射文件,配置信息、生成的相應(yīng)對象都會保存至Configuration全局配置對象中
3. 構(gòu)建一個DefaultSqlSessionFactory對象
XMLConfigBuilder
org.apache.ibatis.builder.xml.XMLConfigBuilder:根據(jù)配置文件進行解析,開始Mapper接口與XML映射文件的初始化,生成Configuration全局配置對象
構(gòu)造方法
public XMLConfigBuilder(Reader reader, String environment, Properties props) {
this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
}
private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
// <1> 創(chuàng)建 Configuration 對象
super(new Configuration());
// 創(chuàng)建一個當(dāng)前線程的上下文,記錄錯誤信息
ErrorContext.instance().resource("SQL Mapper Configuration");
// <2> 設(shè)置 Configuration 的 variables 屬性
this.configuration.setVariables(props);
this.parsed = false;
this.environment = environment;
this.parser = parser;
}
1. 首先會進入XPathParser的構(gòu)造方法,將XML配置文件解析成org.w3c.dom.Document對象,這里傳入了XMLMapperEntityResolver作為解析實例對象,其中使用到MyBatis本地的DTD文件
2. 然后進入XMLConfigBuilder的另一個構(gòu)造方法,會先創(chuàng)建一個Configuration全局配置對象,初始化一些對象
parse方法
public Configuration parse() {
// <1.1> 若已解析,拋出 BuilderException 異常
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
// <1.2> 標(biāo)記已解析
parsed = true;
// <2> 解析 XML configuration 節(jié)點
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
private void parseConfiguration(XNode root) {
try {
// issue #117 read properties first
// <1> 解析 標(biāo)簽
propertiesElement(root.evalNode("properties"));
// <2> 解析 標(biāo)簽,解析配置生成 Properties 對象
Properties settings = settingsAsProperties(root.evalNode("settings"));
// 根據(jù)配置加載自定義 VFS 實現(xiàn)類
loadCustomVfs(settings);
// 根據(jù)配置加載自定義的 Log 實現(xiàn)類
loadCustomLogImpl(settings);
// <3> 解析 標(biāo)簽,生成別名與類的映射關(guān)系
typeAliasesElement(root.evalNode("typeAliases"));
// <4> 解析 標(biāo)簽,添加自定義攔截器插件
pluginElement(root.evalNode("plugins"));
// <5> 解析 標(biāo)簽,自定義實例工廠
objectFactoryElement(root.evalNode("objectFactory"));
// <6> 解析 標(biāo)簽,自定義 ObjectWrapperFactory 工廠,無默認(rèn)實現(xiàn)
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
// <7> 解析 標(biāo)簽,自定義 Reflector 工廠
reflectorFactoryElement(root.evalNode("reflectorFactory"));
// 將 配置信息添加到 Configuration 屬性
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
// <8> 解析 標(biāo)簽,自定義當(dāng)前環(huán)境信息
environmentsElement(root.evalNode("environments"));
// <9> 解析 標(biāo)簽,數(shù)據(jù)庫標(biāo)識符
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
// <10> 解析 標(biāo)簽,自定義類型處理器
typeHandlerElement(root.evalNode("typeHandlers"));
// <11> 解析 標(biāo)簽,掃描Mapper接口并進行解析
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
在parse()解析方法中,獲取到Document對象的節(jié)點,然后調(diào)用parseConfiguration進行解析,依次解析以下標(biāo)簽:
<1> 解析 標(biāo)簽,調(diào)用propertiesElement方法
<2>解析標(biāo)簽,解析配置生成 Properties 對象,調(diào)用settingsAsProperties方法
<3> 解析標(biāo)簽,生成別名與類的映射關(guān)系,調(diào)用typeAliasesElement方法
<4> 解析標(biāo)簽,添加自定義攔截器插件,調(diào)用pluginElement方法
<5> 解析標(biāo)簽,自定義實例工廠,調(diào)用objectFactoryElement方法
<6>解析 標(biāo)簽,自定義 ObjectWrapperFactory 工廠,調(diào)用objectWrapperFactoryElement方法
<7> 解析標(biāo)簽,自定義 Reflector 工廠,調(diào)用reflectorFactoryElement方法
<8> 解析標(biāo)簽,自定義當(dāng)前環(huán)境信息,調(diào)用environmentsElement方法
<9>解析標(biāo)簽,數(shù)據(jù)庫標(biāo)識符,調(diào)用databaseIdProviderElement方法
<10>解析標(biāo)簽,自定義類型處理器,調(diào)用typeHandlerElement方法
<11> 解析標(biāo)簽,掃描Mapper接口并進行解析,調(diào)用mapperElement方法
關(guān)于MyBatis的配置描述請參考MyBatis官方文檔的配置說明
上面涉及到的解析方法就不一一列出來了
總結(jié)
以上是生活随笔為你收集整理的inputstream 初始化_MyBatis初始化之加载初始化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nginx 反向代理跨域访问配置_ngi
- 下一篇: c++根据二叉树的层次遍历建立二叉树_L