本文來自http://www.bubuko.com/infodetail-549184.htmlphp
若是不太熟悉MyBatis使用的請先參見MyBatis官方文檔,這對理解其架構設計和源碼分析有很大好處。html
MyBatis並非一個完整的ORM框架,其官方首頁是這麼介紹本身java
The MyBatis data mapper framework makes it easier to use a relational database with object-oriented applications. MyBatis couples objects with stored procedures or SQL statements using a XML descriptor or annotations. Simplicity is the biggest advantage of the MyBatis data mapper over object relational mapping tools.
而在其官方文檔中介紹「What is MyBaits」中說到git
MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. MyBatis eliminates almost all of the JDBC code and manual setting of parameters and retrieval of results. MyBatis can use simple XML or Annotations for configuration and map primitives, Map interfaces and Java POJOs (Plain Old Java Objects) to database records.
下面是從功能流程層次描述MyBatis的總體架構圖github
而下面是MyBatis源碼包對應的架構圖sql
下面以「功能流程角度的架構圖」來簡要地分析下各層的架構,在後面系列文章中將有專題來深刻解析MyBatis重要的功能點。數據庫
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
try {
Blog blog = session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
} finally {
session.close();
}
SqlSessionFactory、SqlSession這是MyBatis接口層的核心類,尤爲是SqlSession,是實現全部數據庫操做的API,這幾個類都是org.apache.ibatis.session包下的,這個包的主體類結構圖以下apache
Configuration是MyBatis中至關重要的一個類,能夠這麼說,若是理解了其中的全部參數的意義,不只清楚地知道MyBatis提供的全部配置項,還理解了MyBatis的內部核心運行原理,固然要真正理解這些參數的意義及實現,還須要閱讀完完整的MyBatis框架以後才能作到。緩存
由上圖能夠看到,Configuration對象與DefaultSqlSessionFactory是1:1的關聯關係,這也就意味着在一個DefaultSqlSessionFactory衍生出來的全部SqlSession做用域裏,Configuration對象是全局惟一的。同時SqlSessionFactory提供了getConfiguration()接口來公開Configuration對象,所以開發者除了配置文件以外,還能夠在程序裏動態更改Configuration的屬性項以達到動態調整的目的,但此時不只要考慮到執行完reset,同時還要考慮在修改過程當中會可能影響到其餘SqlSession的執行。安全
在應用啓動的時候,MyBatis解析兩種配置文件
SqlMapConfig.xml是在XMLConfigBuilder類中完成解析的,其類圖關係大體以下
咱們知道XML有兩種解析方式:一是DOM,另外一個是SAX,MyBatis使用的是org.wrc.dom——JDK提供的文檔對象模型(DOM)接口(SqlMapConfig.xml並不大,因此DOM方式並無什麼效率損耗,JDK也提供了SAX模型接口org.xml.sax,這兩個都是JAXP的組件API),以及JDK官方提供的javax.xml.xpath.XPath來做爲XML路徑尋找組件。
SqlMap.xml是在XMLMapperBuilder中解析完成的,其中把對Statement的解析(即SqlMap.xml中SELECT|INSERT|UPDATE|DELETE定義部分)委託給XMLStatementBuilder來完成。SqlMap.xml的解析比較複雜的,涉及到PreparedMapping、ResultMapping、LanguageDriver、Discriminator、緩存、自動映射等一系列對象的構造,這裏暫時略過,後面專題分析。
MyBatis中Executor是的核心,圍繞着它完成了數據庫操做的完整過程。下面是Executor的類圖
在上圖中我列出了Executor中方法的參數,而在其子類中就沒有明確寫出。從上圖中能夠看到,Executor主要提供了
BaseExecutor的屬性代表:它內部維護了localCache來localOutputParameterCache來處理緩存,至於這緩存保存的是什麼,這後面專題再說。以及線程安全的延遲加載列表deferredLoads、事務對象Transaction。
BatchExecutor的屬性已經代表:它內部維護了StatementList批量提交併經過batchResultList保存執行結果。
ResueExecutor的屬性及方法代表:它內部維護了java.sql.Statement對象緩存,以重用Statement對象(對於支持預編譯的數據庫而言,在建立PreparedStatement時須要發送一次數據庫請求預編譯,而重用Statement對象主要是減小了此次預編譯的網路開銷)。
下面以SqlSession.selectList爲例,畫出SQL執行的時序圖(點擊下方的圖片查看大圖,部分分支有所簡化)
MyBatis使用了本身定義的一套logging接口,根據開發者常使用的日誌框架——Log4j、Log4j二、Apache Commons Log、java.util.logging、slf4j、stdout(控制檯)——分別提供了適配器。因爲各日誌框架的Log級別分類法有所不一樣(好比java.util.logging.Level提供的是All、FINEST、FINER、FINE、CONFIG、INFO、WARNING、SEVERE、OFF這九個級別,與一般的日誌框架分類法不太同樣),MyBatis統一提供trace、debug、warn、error四個級別,這基本與主流框架分類法是一致的(相比而言缺乏Info,也許MyBatis認爲本身的日誌要麼是debug須要的,要麼就至少是warn,沒有Info的必要)。
在org.apache.ibatis.logging裏還有個比較特殊的包jdbc,這不是按字面意義理解把日誌經過jdbc記錄到數據庫裏,而是將jdbc操做以開發者配置的日誌框架打印出來,這也就是咱們在開發階段經常使用的跟蹤SQL語句、傳入參數、影響行數這些重要的調試信息。
MyBatis裏的IO主要是包含兩大功能:提供讀取資源文件的API、封裝MyBatis自身所須要的ClassLoader和加載順序。
在MyBatis如參數處理、結果映射這些大量地使用了反射,須要頻繁地讀取Class元數據、反射調用get/set,所以MyBatis提供了org.apache.ibatis.reflection對常見的反射操做進一步封裝,以提供更簡潔方便的API。好比咱們reflect時老是要處理異常(IllegalAccessException、NoSuchMethodException),MyBatis統一處理爲自定義的RuntimeException,減小代碼量。
在以Spring爲表明的開源框架中,對於應用程序中沒法進一步處理的異常大都轉成RuntimeException來方便調用者操做,另外如頻繁遇到的SQLException,JDK約定其是個Exception,從JDK的角度考慮,強制要求開發者捕獲SQLException是爲了能在catch/finally中關閉數據庫鏈接,而Spring之類的框架爲開發者作了資源管理的事情,天然就不須要開發者再煩心SQLException,所以封裝轉換成RuntimeException。MyBatis的異常體系不復雜,org.apache.ibatis.exceptions下就幾個類,主要被使用的是PersistenceException。
緩存是MyBatis裏比較重要的部分,有兩種緩存:
MyBatis自身提供了一個簡易的數據源/鏈接池,在org.apache.ibatis.datasource下,後面專題分析。主要實現類是PooledDataSource,包含了最大活動鏈接數、最大空閒鏈接數、最長取出時間(避免某個線程過分佔用)、鏈接不夠時的等待時間,雖然簡單,卻也體現了鏈接池的通常原理。阿里有個「druid」項目,據他們說比proxool、c3p0的效率還要高,能夠學習一下。
MyBatis對事務的處理相對簡單,TransactionIsolationLevel中定義了幾種隔離級別,並不支持內嵌事務這樣較複雜的場景,同時因爲其是持久層的緣故,因此真正在應用開發中會委託Spring來處理事務實現真正的與開發者隔離。分析事務的實現是個入口,藉此能夠了解不掃JDBC規範方面的事情。
後續將對MyBatis各個部分作詳細的設計及源代碼分析,因爲讀取和解析SqlMapConfig.xml和SqlMap.xml的邏輯與各個模塊的相關性較強,所以將把這部份內容與在各模塊組合在一塊兒分析。
感謝本文原創做者,可是木有找到。。。