這篇文章咱們來深刻閱讀下Mybatis的源碼,但願之後能夠對底層框架不那麼畏懼,學習框架設計中好的思想;
上面這兩幅圖來源於網絡,不過畫的很好,基本說明了Mybatis的架構流程。java
說明:node
Mybatis配置文件mysql
SqlSessionFactory程序員
SqlSessionsql
Executor執行器數據庫
MappedStatement編程
Executor設計模式
MyBatis執行器,是MyBatis 調度的核心,負責SQL語句的生成和查詢緩存的維護api
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 構建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:解析全局配置文件中的<mappers>標籤 |--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 |--MappedStatement
XMLLanguageDriver#createSqlSource 建立SqlSource,解析SQL,封裝SQL語句(出參數綁定)和入參信息 XMLScriptBuilder 構造函數:初始化動態SQL中的節點處理器集合 XMLScriptBuilder#parseScriptNode #parseDynamicTags 解析select\insert\ update\delete標籤中的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
|--DefaultSqlSession#getMapper:獲取Mapper代理對象 |--Configuration#getMapper:獲取Mapper代理對象 |--MapperRegistry#getMapper:經過代理對象工廠,獲取代理對象 |--MapperProxyFactory#newInstance:調用JDK的動態代理方式,建立Mapper代理
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
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對象中
|--PreparedStatementHandler#parameterize:設置PreparedStatement的參數 |--DefaultParameterHandler#setParameters:設置參數 |--BaseTypeHandler#setParameter: |--xxxTypeHandler#setNonNullParameter:調用PreparedStatement的setxxx方法
|--DefaultResultSetHandler#handleResultSets |--DefaultResultSetHandler#handleResultSet |--DefaultResultSetHandler#handleRowValues |--DefaultResultSetHandler#handleRowValuesForSimpleResultMap |--DefaultResultSetHandler#getRowValue |--DefaultResultSetHandler#createResultObject:建立映射結果對象 |--DefaultResultSetHandler#applyAutomaticMappings |--DefaultResultSetHandler#applyPropertyMappings
基本上Mybatis的流程就是這樣了,其中還有不少實現細節暫時看不太懂。 我認爲學習框架源碼分爲兩步:
目前第一步尚有問題,須要多走幾遍源碼,加深下理解,一塊兒加油~~