Mybatis源碼解析之初始化分析
一、 Mybatis配置文件
configuation是mybatis配置文件的根節(jié)點(diǎn)。
configuration 配置 -properties 屬性 -settings 設(shè)置 -typeAliases 類型別名 -typeHandlers 類型處理器 -objectFactory 對(duì)象工廠 -plugins 插件 -environments 環(huán)境 -environment 環(huán)境變量 -transactionManager 事務(wù)管理器 -dataSource 數(shù)據(jù)源 -databaseIdProvider 數(shù)據(jù)庫(kù)廠商標(biāo)識(shí) -mappers 映射器
本文主要講解源碼,不對(duì)配置文件展開
二、配置文件解析過(guò)程
1. 初始化demo
下文代碼是mybatis通過(guò)解析xml配置文件進(jìn)行初始化的一個(gè)簡(jiǎn)單demo,后續(xù)我們將根據(jù)這個(gè)demo追蹤mybatis源碼的處理過(guò)程。
InputStream inputStream = Resources.getResourceAsStream("mybatis-coonfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
2. SqlSessionFactoryBuilder#build(InputStream, String. Properties)
SqlSessionFactoryBuilder的build(inputStream)方法通過(guò)調(diào)用同名的重載方法SqlSessionFactoryBuilder#build(InputStream, String. Properties)來(lái)生成需要的SqlSessionFacotry。
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.
}
}
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}首先,通過(guò)XmlConfigBuilder解析配置文件,并得到configuration類對(duì)象。 然后根據(jù)configuration作為參數(shù)調(diào)用build得到所需的SqlSessionFactory,可以看到最終得到的SqlSessionFactory類型是DefaultSqlSessionFactory。
3. XMLConfigBuilder#parse()
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
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);
}
}可以看到,XMLConfigBuilder對(duì)xml配置文件中對(duì)configuration的子節(jié)點(diǎn)進(jìn)行逐個(gè)解析。 以typeAliases為例,遍歷typeAliases的子節(jié)點(diǎn),根據(jù)配置情況將其加入到configuration對(duì)象中對(duì)應(yīng)的typeAliasRegistry屬性,其它節(jié)點(diǎn)的解析也類似。
private void typeAliasesElement(XNode parent) {
if (parent != null) {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
String typeAliasPackage = child.getStringAttribute("name");
configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);
} else {
String alias = child.getStringAttribute("alias");
String type = child.getStringAttribute("type");
try {
Class<?> clazz = Resources.classForName(type);
if (alias == null) {
typeAliasRegistry.registerAlias(clazz);
} else {
typeAliasRegistry.registerAlias(alias, clazz);
}
} catch (ClassNotFoundException e) {
throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e);
}
}
}
}
}4. DefaultSqlSessionFactory#openSession()
@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}DefaultSqlSessionFactory#openSession()最終通過(guò)DefaultSqlSessionFactory#openSessionFromDataSource(ExecutorType, TransactionLevel, boolean)試下,可以看到最后獲得的SqlSession類型是DefaultSqlSession,其中executor類型是SimpleExecutor。
到此這篇關(guān)于Mybatis源碼解析之初始化分析的文章就介紹到這了,更多相關(guān)Mybatis初始化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
List調(diào)用toString()方法后,去除兩頭的中括號(hào)實(shí)例
下面小編就為大家?guī)?lái)一篇List調(diào)用toString()方法后,去除兩頭的中括號(hào)實(shí)例。希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-03-03
SpringBoot 中html的頁(yè)面間跳轉(zhuǎn)問(wèn)題小結(jié)
這篇文章主要介紹了SpringBoot 中html的頁(yè)面間跳轉(zhuǎn)問(wèn)題小結(jié),本文給大家分享兩種方法,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10
Java SE使用數(shù)組實(shí)現(xiàn)高速數(shù)字轉(zhuǎn)換功能
隨著大數(shù)據(jù)時(shí)代的到來(lái),數(shù)字轉(zhuǎn)換功能變得越來(lái)越重要,在Java開發(fā)中,數(shù)字轉(zhuǎn)換功能也是經(jīng)常用到的,下面我們就來(lái)學(xué)習(xí)一下如何使用Java SE數(shù)組實(shí)現(xiàn)高速的數(shù)字轉(zhuǎn)換功能吧2023-11-11
Java-web中利用RSA進(jìn)行加密解密操作的方法示例
這篇文章主要給大家介紹了關(guān)于在Java-web中利用RSA進(jìn)行加密解密操作的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08
Mac配置 maven以及環(huán)境變量設(shè)置方式
這篇文章主要介紹了Mac配置 maven以及環(huán)境變量設(shè)置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
SpringBoot引入swagger報(bào)錯(cuò)處理的解決方法
這篇文章主要給大家介紹SpringBoot引入swagger是會(huì)出現(xiàn)報(bào)錯(cuò)的處理解決方法,文中有詳細(xì)的解決過(guò)程,感興趣的小伙伴可以跟著小編一起來(lái)學(xué)習(xí)吧2023-06-06

