摘要:我認為學習框架源碼分為兩步抓住主線,掌握框架的原理和流程理解了處理思路之后,再去理解面向對象思想和設計模式的用法目前第一步尚有問題,需要多走幾遍源碼,加深下理解,一起加油
這篇文章我們來深入閱讀下Mybatis的源碼,希望以后可以對底層框架不那么畏懼,學習框架設計中好的思想;架構原理 架構圖 架構流程圖
上面這兩幅圖來源于網絡,不過畫的很好,基本說明了Mybatis的架構流程。
說明:
Mybatis配置文件
SqlMapConfig.xml,此文件作為mybatis的全局配置文件,配置了mybatis的運行環境等信息。
Mapper.xml,此文件作為mybatis的sql映射文件,文件中配置了操作數據庫的sql語句。此文件需要在 SqlMapConfig.xml中加載。
SqlSessionFactory
通過mybatis環境等配置信息構造SqlSessionFactory,即會話工廠。
SqlSession
通過會話工廠創建sqlSession即會話,程序員通過sqlsession會話接口對數據庫進行增刪改查操作。
Executor執行器
mybatis底層自定義了Executor執行器接口來具體操作數據庫,Executor接口有兩個實現,一個是基本執行器(默認)、一個是緩存執行器,sqlsession底層是通過executor接口操作數據庫的。
MappedStatement
它也是mybatis一個底層封裝對象,它包裝了mybatis配置信息及sql映射信息等。mapper.xml文件中一個selectinsertupdatedelete標簽對應一個Mapped Statement對象,selectinsertupdatedelete標簽的id即是Mapped statement的id。
Mapped Statement對sql執行輸入參數進行定義,包括HashMap、基本類型、pojo,Executor通過MappedStatement在執行sql前將輸入的java對象映射至sql中,輸入參數映射就是jdbc編程中對preparedStatement設置參數。
Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本類型、pojo,Executor通過MappedStatement在執行sql后將輸出結果映射至java對象中,輸出結果映射過程相當于jdbc編程中對結果的解析處理過程。
調用流程圖Executor
MyBatis執行器,是MyBatis 調度的核心,負責SQL語句的生成和查詢緩存的維護
StatementHandler
封裝了JDBC Statement操作,負責對JDBC statement 的操作,如設置參數、將Statement結果集轉換成List集合。
ParameterHandler
負責對用戶傳遞的參數轉換成JDBC Statement 所需要的參數
ResultSetHandler
負責將JDBC返回的ResultSet結果集對象轉換成List類型的集合
TypeHandler
負責java數據類型和jdbc數據類型之間的映射和轉換
SqlSource
負責根據用戶傳遞的parameterObject,動態地生成SQL語句,將信息封裝到BoundSql對象中,并返回BoundSql表示動態生成的SQL語句以及相應的參數信息
源碼解析 加載全局配置文件找入口:SqlSessionFactoryBuilder#build方法
SqlSessionFactoryBuilder#build 構建SqlSessionFactory XMLConfigBuilder#parse 全局配置文件解析,封裝成Configuration對象 #parseConfiguration 從根路徑開始解析,加載的信息設置到Configuration對象中 #mapperElement 解析mapper映射文件 XMLMapperBuilder#parse 具體解析mapper映射文件 SqlSessionFactoryBuilder#build:創建SqlSessionFactory接口的默認實現類
總結
1.SqlSessionFactoryBuilder創建SqlsessionFactory時,需要傳入一個Configuration對象。 2.XMLConfigBuilder對象會去實例化Configuration。 3.XMLConfigBuilder對象會去初始化Configuration對象。 通過XPathParser去解析全局配置文件,形成Document對象 通過XPathParser去獲取指定節點的XNode對象。 解析Xnode對象的信息,然后封裝到Configuration對象中
相關類和接口
|--SqlSessionFactoryBuilder |--XMLConfigBuilder |--XPathParser |--Configuration加載映射配置文件
找入口:XMLConfigBuilder#mapperElement方法
XMLConfigBuilder#mapperElement:解析全局配置文件中的標簽 |--XMLMapperBuilder#構造方法:專門用來解析映射文件的 |--XPathParser#構造方法: |--XPathParser#createDocument():創建Mapper映射文件對應的Document對象 |--MapperBuilderAssistant#構造方法:用于構建MappedStatement對象的 |--XMLMapperBuilder#parse(): |--XMLMapperBuilder#configurationElement:專門用來解析mapper映射文件 |--XMLMapperBuilder#buildStatementFromContext:用來創建MappedStatement對象的 |--XMLMapperBuilder#buildStatementFromContext |--XMLStatementBuilder#構造方法:專門用來解析MappedStatement |--XMLStatementBuilder#parseStatementNode: |--MapperBuilderAssistant#addMappedStatement:創建 MappedStatement對象 |--MappedStatement.Builder#構造方法 |--MappedStatement.Builder#build方法:創建MappedStatement對象,并存儲 到Configuration對象中
相關接口和類
|--XMLConfigBuilder |--XMLMapperBuilder |--XPathParser |--MapperBuilderAssistant |--XMLStatementBuilder |--MappedStatementSqlSource創建流程
找入口:XMLLanguageDriver#createSqlSource
XMLLanguageDriver#createSqlSource 創建SqlSource,解析SQL,封裝SQL語句(出參數綁定)和入參信息 ? XMLScriptBuilder 構造函數:初始化動態SQL中的節點處理器集合 ? XMLScriptBuilder#parseScriptNode ? #parseDynamicTags 解析selectinsert updatedelete標簽中的SQL語句,最終將解析到的SqlNode封裝到MixedSqlNode中的List集合中 ? DynamicSqlSource 構造方法:如果SQL中包含${}和動態SQL語句,則將SqlNode封裝到DynamicSqlSource ? RawSqlSource 構造方法:如果SQL中包含#{},則將SqlNode封裝到RawSqlSource中,并指定parameterType ? SqlSourceBuilder#parse ? ParameterMappingTokenHandler 構造方法 ? GenericTokenParser#構造方法,指定待分析的openToken和closeToken并指定處理器 ? GenericTokenParser#parse 解析#{} ? ParameterMappingTokenHandler#handleToken 處理token(#{}/${}) ? #buildParameterMapping 創建ParameterMapping對象 ? StaticSqlSource 構造方法,將解析之后的sql信息,封裝到StaticSqlSource 對象
相關類和接口
|--XMLLanguageDriver |--XMLScriptBuilder |--SqlSource |--SqlSourceBuilder創建Mapper代理對象
找入口:DefaultSqlSession#getMapper
|--DefaultSqlSession#getMapper:獲取Mapper代理對象 ? |--Configuration#getMapper:獲取Mapper代理對象 ? |--MapperRegistry#getMapper:通過代理對象工廠,獲取代理對象 ? |--MapperProxyFactory#newInstance:調用JDK的動態代理方式,創建Mapper代理SqlSession執行主流程
找入口:DefaultSqlSession#selectList()
DefaultSqlSession#selectList ? CachingExecutor#query ? BaseExecutor#query 委托給BaseExecutor執行 ? #queryFromDatabase ? SimpleExecutor#doQuery 執行查詢 ? Configuration#newStatementHandler 創建路由功能的StatementHandler,根據MappedStatement中的StatementType ? SimpleExecutor#prepareStatement 設置PreapreStatement 的參數 ? BaseExecutor#getConnection 獲取數據庫連接 ? BaseStatementHandler#prepare 創建Statement PrepareStatement、Statement、CallableStatement) ? PreparedStatementHandler#parameterize 設置參數 ? PreparedStatementHandler#query 執行SQL語句(已經設置過參數),并且映射結果集 ? com.mysql.jdbc.PreparedStatement#execute 調用JDBC的api執行Statement ? DefaultResultSetHandler#handleResultSets 處理結果集
相關接口和類
|--DefaultSqlSession |--Executor |--CachingExecutor |--BaseExecutor |--SimpleExecutor |--StatementHandler |--RoutingStatementHandler |--PreparedStatementHandler |--ResultSetHandler |--DefaultResultSetHandler
?
BoundSql獲取流程找入口:MappedStatement#getBoundSql方法
MappedStatement#getBoundSql ? DynamicSqlSource#getBoundSql ? SqlSourceBuilder#parse 執行解析:將帶有#{}的SQL語句進行解析,然后封裝到StaticSqlSource中 ? GenericTokenParser #構造方法,指定待分析的openToken和closeToken,并指定處理器 ? GenericTokenParser#parse 解析SQL語句,處理openToken和closeToken中的內容 ? ParameterMappingTokenHandler#handleToken 處理token(#{}/${}) ? #buildParameterMapping 創建 ParameterMapping對象 ? StaticSqlSource#構造方法 : 將解析之后的SQL信息,封裝到StaticSqlSource |--RawSqlSource#getBoundSql ? |--StaticSqlSource#getBoundSql ? |--BoundSql#構造方法:將解析后的sql信息、參數映射信息、入參對象組合到BoundSql對象中參數映射流程
找入口: 其實就是SqlSession執行流程中的 PreparedStatementHandler#parameterize
|--PreparedStatementHandler#parameterize:設置PreparedStatement的參數 ? |--DefaultParameterHandler#setParameters:設置參數 ? |--BaseTypeHandler#setParameter: ? |--xxxTypeHandler#setNonNullParameter:調用PreparedStatement的setxxx方法處理結果集
找入口:其實就是SqlSession執行流程中的 DefaultResultSetHandler#handleResultSets
|--DefaultResultSetHandler#handleResultSets ? |--DefaultResultSetHandler#handleResultSet ? |--DefaultResultSetHandler#handleRowValues ? |--DefaultResultSetHandler#handleRowValuesForSimpleResultMap ? |--DefaultResultSetHandler#getRowValue ? |--DefaultResultSetHandler#createResultObject:創建映射結果對象 ? |--DefaultResultSetHandler#applyAutomaticMappings ? |--DefaultResultSetHandler#applyPropertyMappings
基本上Mybatis的流程就是這樣了,其中還有很多實現細節暫時看不太懂。 我認為學習框架源碼分為兩步:
抓住主線,掌握框架的原理和流程;
理解了處理思路之后,再去理解面向對象思想和設計模式的用法;
目前第一步尚有問題,需要多走幾遍源碼,加深下理解,一起加油~~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75639.html
摘要:簡介我從七月份開始閱讀源碼,并在隨后的天內陸續更新了篇文章。考慮到超長文章對讀者不太友好,以及拆分文章工作量也不小等問題。經過兩周緊張的排版,一本小小的源碼分析書誕生了。我在寫系列文章中,買了一本書作為參考,這本書是技術內幕。 1.簡介 我從七月份開始閱讀MyBatis源碼,并在隨后的40天內陸續更新了7篇文章。起初,我只是打算通過博客的形式進行分享。但在寫作的過程中,發現要分析的代碼...
摘要:核心包包名稱包內內容簡介注解目錄。如等類的實例反射生成工具目錄主要是注解,和的構造器及轉換器內部緩存接口。等默認的游標處理類數據源工廠類及實現。數據源實現類自定義的三個異常類。。都繼承自執行器相關包。為后續分析源碼打下基礎。 Mybatis核心包 showImg(https://segmentfault.com/img/remote/1460000018747383?w=746&h=1...
摘要:下面我會詳細地從源碼的角度分析下文簡寫成是如何實現自動注入的原理。文件解析器,解析對應的文件信息,并將文件信息注冊到中。節點解析器,用于構建節點信息。注冊與綁定類,將的類信息與綁定。 微信公眾號「后端進階」,專注后端技術分享:Java、Golang、WEB框架、分布式中間件、服務治理等等。 老司機傾囊相授,帶你一路進階,來不及解釋了快上車! mybatis-plus是完全基于myba...
摘要:哪吒社區技能樹打卡打卡貼函數式接口簡介領域優質創作者哪吒公眾號作者架構師奮斗者掃描主頁左側二維碼,加入群聊,一起學習一起進步歡迎點贊收藏留言前情提要無意間聽到領導們的談話,現在公司的現狀是碼農太多,但能獨立帶隊的人太少,簡而言之,不缺干 ? 哪吒社區Java技能樹打卡?【打卡貼 day2...
摘要:一級緩存介紹及相關配置。在這個章節,我們學習如何使用的一級緩存。一級緩存實驗配置完畢后,通過實驗的方式了解一級緩存的效果。源碼分析了解具體的工作流程后,我們隊查詢相關的核心類和一級緩存的源碼進行走讀。 我,后端Java工程師,現在美團點評工作。愛健身,愛技術,也喜歡寫點文字。個人網站: http://kailuncen.me公眾號: KailunTalk (凱倫說) 前言 本文主要涉及...
閱讀 1379·2023-04-25 18:34
閱讀 3437·2021-11-19 09:40
閱讀 2824·2021-11-17 09:33
閱讀 2935·2021-11-12 10:36
閱讀 2823·2021-09-26 09:55
閱讀 2653·2021-08-05 10:03
閱讀 2512·2019-08-30 15:54
閱讀 2861·2019-08-30 15:54