一次Mybatis部分源碼閱讀

Mybatis是ORM層的解決方案,其特性包括延遲加載,緩存等。既然是ORM層的解決方案,本質上當然是幫助我們更合理的去訪問數據庫,所以延遲加載和緩存打算以後再看,今天只閱讀了部分源碼,梳理一下Mybatis是如何幫助我們操作數據庫的。

可以先梳理一下如果沒有Mybatis,我們是怎麼利用JDBC去訪問數據庫的,這麼幾個步驟:

1.Class.forName()加載驅動。這兒有個題外話,爲什麼這裏的類加載用Class.forName()而不用類加載器是因爲前者加載後可以進行初始化階段,這是需要的,而後者不可以。

2.DriverManager.getConnection()獲得連接connection。

3.connection.createStatement()創建statement。

4.statement.executeUpdate()/statement.executeQuery()執行SQL。

5.用ResultSet接受上一步的執行結果,在去遍歷解析。

6.如果之前connection.setAutoCommit(false)設置了關閉自動提交事務,還要connection.commit()提交事務。

7.最後還要記得依次關閉resultset,statement,connection。

原始而又複雜,這個時候解決方案Mybatis就來了。

Mybatis引入了一個sqlSession的概念,這是一個接口。可以看看裏面有哪些抽象方法。

調用這些方法是不是彷彿自己在用執行SQL操作數據庫?居然還有事務。可以把它理解爲Mybatis暴露給我們的操作數據庫的入口,那怎麼拿到它呢?有一個SqlSessionFactory,這是個接口,DefaultSqlSessionFactory實現了它,看類名也看出來了,利用了工廠模式,該類裏面重載了很多opsession()方法去獲得sqlsession。

怎麼拿倒不是關鍵的,從我們利用Mybatis的編碼中也可以看出來怎麼拿。

重要的是拿之前當然要構建sqlsession了,既然是從sqlsessionFactory裏面拿的,當然是要先構建sqlsessionFactory了,我們是通過SqlSessionFactoryBuilder去構建的,其build()方法源碼如圖:

這個build()方法可以分這麼幾步理解,構建sqlsessionFactory需要知道構建成什麼樣子的啊即要知道相關配置Configuration,那就是先構建Configuration對象了。

1.把配置文件裏的相關配置讀出來初始化好

2.知道相關配置了,那就去構建Configuration對象吧

3.既然有了Configuration那就去構建sqlsessionFactory吧

分開來詳細梳理一下:

第一步:把配置文件裏的相關配置讀出來初始化好,即

XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);

這個初始化過程直接貼圖:

 XMLConfiguration的構造需要三個參數,輸入流inputStream/reader,String類型的environment和配置類Properties對象,XMLConfigBuilder會利用輸入流和Properties對象構建了一個XPathParse對象,然後this()調用另一個構造方法,因爲Configuration是其父類BaseBuilder的屬性,在這個構造方法裏,先super()初始化Configuration對象,再初始化其他屬性,比如environment,值得注意的是把一個布爾型parsed設置爲false,這個兩個屬性的作用後面會說。下面兩張圖是XPathParse對象的初始化過程:

 

到這裏爲止只是做了一個屬性的初始化工作。核心還是下面的parse()方法。

第二步:知道相關配置了,那就去構建Configuration對象吧,即

parser.parse()

先貼parse()源碼:

該方法的返回類型果然是Configuration,在這個方法裏,剛擱置的那個布爾型parsed就有用了,它是用來控制這個XMLConfiguration只被使用一次,即parse()方法拿到Configuration對象只能被調用一次 。因爲調用這個方法後parsed會被設置爲true,就理解成調用過了嘛,parse()方法進來會有一個判斷,使用過了?那就拋異常吧。然後是使用XPathParser對象的evalNode方法獲取配置文件的裏內容,就我們寫在<configuration></configuration>裏的東西。再然後就是核心了,在parseConfiguration()方法裏分別給Configuration對象設置屬性。這個方法裏調用了這麼多方法,其實這些方法最後都是各種configuration.set.../add...,可以注意一下其中一個mapperElement(),這個方法裏就是可以讓我們寫的這麼多SQL在mapper.XML生效,看一眼它的源碼應該就可以理解了,各種name,url,resource,很熟悉吧。

到這裏Configuration對象也拿到了。接下來就是最後一步了。

第三步:既然有了Configuration那就去構建sqlsessionFactory吧,即

var5 = this.build(parser.parse());

先看這個build()裏是什麼:

嗷~,原來是構建了一個 DefaultSqlSessionFactory,那就去看看吧:

 這個DefaultSqlSessionFactory實現了SqlSessionFactory,看來到頭了,源碼讀到這裏,上訴三步梳理完了,已經知道SqlSessionFactory怎麼來的了。我們在編碼中會利用SqlSessionFactory的openSession()拿到sqlSession去操作數據庫,那就繼續看sqlSession怎麼來的吧。

知道相關配置的DefaultSqlSessionFactory是怎麼通過一系列的opsession方法去構建sqlsession的呢?這麼多重載的openSession方法裏面都是選着調用了openSessionFromDataSource()或者openSessionFromConnection(),兩個方法邏輯差不過,前者比較常用,先貼圖:

主要是先利用TransactionFactory對象構建了事務,用到了剛說的String類型的envirenment變量,還構建了Executor對象,這是Mybatis的一個核心,構建過程就不看了,可以看Executor這個接口裏有哪些方法:

可以理解爲一個調度對象,Mybatis真正操作數據庫的對象,有CRUD,有事務提交回滾,有緩存操作還有關閉連接等。還是貼一看Executor對象的構建過程吧:

 有了Executor調度對象和配置Configuration就可以去構建sqlSession了,即

var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);

new了一個DefaultSqlSession對象,它是SqlSession的實現類,剩下的就是一些初始化工作:

 到這裏就讀完了,但是上面的流程是MyBatis不和Spring整合自己怎麼拿到sqlSession的,如果整合進spring,一開始的步驟會有點不一樣,spring的配置類文件springConfiguration裏可以重寫一個sqlSessionFactoryBean()方法,這個方法返回值類型就是sqlSessionFactoryBean,我們需要做的就是給這個sqlSessionFactoryBean各種設置屬性。

Spring自己會利用sqlSessionFactoryBean對象的buildSqlSessionFactory()方法獲取sqlSessionFactory對象:

XMLConfigBuilder又來了,剩下的就是大同小異了。

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