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ì)配置文件展開(kāi)
二、配置文件解析過(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-03SpringBoot 中html的頁(yè)面間跳轉(zhuǎn)問(wèn)題小結(jié)
這篇文章主要介紹了SpringBoot 中html的頁(yè)面間跳轉(zhuǎn)問(wèn)題小結(jié),本文給大家分享兩種方法,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10Java SE使用數(shù)組實(shí)現(xiàn)高速數(shù)字轉(zhuǎn)換功能
隨著大數(shù)據(jù)時(shí)代的到來(lái),數(shù)字轉(zhuǎn)換功能變得越來(lái)越重要,在Java開(kāi)發(fā)中,數(shù)字轉(zhuǎn)換功能也是經(jīng)常用到的,下面我們就來(lái)學(xué)習(xí)一下如何使用Java SE數(shù)組實(shí)現(xiàn)高速的數(shù)字轉(zhuǎn)換功能吧2023-11-11Java-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-08Mac配置 maven以及環(huán)境變量設(shè)置方式
這篇文章主要介紹了Mac配置 maven以及環(huán)境變量設(shè)置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08SpringBoot引入swagger報(bào)錯(cuò)處理的解決方法
這篇文章主要給大家介紹SpringBoot引入swagger是會(huì)出現(xiàn)報(bào)錯(cuò)的處理解決方法,文中有詳細(xì)的解決過(guò)程,感興趣的小伙伴可以跟著小編一起來(lái)學(xué)習(xí)吧2023-06-06