MyBatis的解析和運行原理

MyBatis的運行可分爲兩大部分,第一部分是讀取配置文件緩存到Configuration對象,用來創建SqlSessionFactory,第二部分是SqlSession的執行過程。

先導入源碼,不然你不知道方法之間是怎麼調用。

一構建SqlSessionFactory過程

第一步,通過org.apache.ibatis.builder.xml.XMLConfigBuilder來解析配置的XML文件。我們一般是能過new SqlSessionFactoryBuilder().build()方法來創建SqlSessionFactory,最終於的是運行build(Reader reader, String environment, Properties properties)這個方法,接着創建一個XMLConfigBuilder對象來解析XML文件,把讀到的數據存入到org.apache.ibatis.session.Configuration中 ,在把數據 存入到Configuration是調用過org.apache.ibatis.builder.xml.XMLConfigBuilderr的parseConfiguration(XNode root)方法,源碼如下:

是不是知道爲什麼Mybatis的核心配置是有順序的,不能打破它的順序。

第二步,通過得到的configuration對象,調用qlSessionFactoryBuilder類中的build(Configuration config)方法,通過這個方法來調用DefaultSqlSessionFactory這類的構造方法

如果你想知道Mybatis所有的配置的信息,除了看API之外,還可以能Configuration的源碼。


二SqlSession運行過程

在舊版本的MyBatis或者是iBatis中,使用的更多是SqlSession接口的方法進行操作,但是有新版的MyBatis建議使用Mapper。

我們一般通過SqlSession的getMapper方法來得到Mapper,面這個方法最終是通過org.apache.ibatis.binding.MapperProxyFactory這個類的newInstance方法產生,這個的重要代碼如下

我們可以看到動態代理對接口的綁定,它的作用就是生成動態代理對象。面代理的方法則被放到了MapperProxy類中。我們還要看MapperProxy的源碼。

看到invoke方法,一旦mapper是一個代理對象,那麼它就會運行到invoke方法裏面,顯然mapper不是一個類,而是接口,所以它會生成MapperMethod對象,它是通過cachedMapperMethod方法對其初始化,然後執行execute方法,把sqlSession各當前運行的參數傳遞進去。我們查看這個方法的源碼:

我主要看result = executeForMany(sqlSession, args);這名個方法,再查看這個方法的源碼:

我們可以看到它最終還調用了SqlSession接口的方法,其它判斷成立的條件,還是調用SqlSession接口的方法。

現在我們可以知道爲什麼MyBatis只用Mapper接口便能夠運行SQL,因爲映射器的XML文件的命名空間對應的便是這個接口的全路徑,那麼它根據全路徑和方法但能夠綁定起來,通過動態代理技術,讓這個接口跑起來。

我們已經知道了映射器其實就是一個代理對象,進入MapperMethod的execute方法,通過簡單判斷就進入SqlSession接口提供的不同方法,但是不知道它們是怎麼樣運行的。Mapper執行的過程是通過Executor(代理執行器)、StatementHandler(使用JDBC的Statement和PrepareStatement進行操作)、ParameterHandler(用於SQL對參數的處理)、ResultHandler(對數據集ResultSet的封裝返回處理)。

執行器(Executor),它是真正執行JAVA與數據庫交互的東西,MyBatis提供了三種執行器,可心根據自己的需求在setting元素的defaultExecutorTope中配置,這裏不介紹,因爲與這篇博客關係不大,自己查API就可以了。我們打開SimpleExecutor這個類,隨便打開找一個方法,這裏爲更好的體現方法的結構,這裏貼的方法如下:

我們可以看到它是根據 Configuration來構建StatementHandler,然後使用prepareStatement方法對SQl編譯 關對參數進行初始化,這個方法調用了StatementHandler的prepare()進行預編譯和基礎配置,然後通過StatementHandler的parameterize()來設置參數並執行。

數據庫會話器(StatementHandler)就是專門處理數據庫會話的,我們通過RoutingStatementHandler來得到StatementHandler對象,它也使用了代理設計模式,StatementHandler分爲三種:CallableStatementHandler、SimpleStatementHandler和PreparedStatementHandler,在初始化的時候會根據上下文環境決定創建那個StatementHandler對象,我們以SimpleStatementHandler爲例,我們 看下面的方法(在運行這個方法,還用調用instantiateStatement方法進行SQL預編譯)

由於執行前參數和SQl都被prepare()方法預編譯,參數在parameterixe()方法上已經進行了設置。

參數處理器(ParameterHandler)對預編譯語句進行參數設置。實現類(DefaultParameterHandler)

結果處理器(ResultSetHandler),實現類(DefaultResultSetHandler),默認情況是通過這個類來處理。

SqlSession運行總結:SqlSession是通過Executo創建StatementHandler來運行的,面StatementHandler要經過下面三步:prepared預編譯SQL;parameterize設置參數;query/執行SQl。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章