看到Mybatis源碼就感到煩躁,怎么辦?
背景
最近,聽到很多吐槽:看到源碼,心中就感到十分糾結(jié)、特別煩惱。
為什么糾結(jié)?
因?yàn)槊嬖嚨臅r(shí)候,面試官很喜歡問:你看過什么框架源碼?JDK源碼也行。
這時(shí)候,如果回答沒有看過,雖然沒讓你立馬回去等通知。但也許,你在面試官心中的印象就大打折扣了。
如果回答看過,并且還能較為流利地說上一番,那面試官或許會(huì)在心里贊嘆:小伙子可以呀!(PS:很多面試官自己也沒看過,或者看過很多也忘了)。
總之,你要是能說上個(gè)123,那給面試官的印象就會(huì)杠杠滴好。何愁工作?何愁加薪?
為什么煩?
大部分人的情況是:源碼不是沒有看過,而是每次只看得下一部分。為什么只看得下一部分呢?通常有下面三種原因:
缺乏技術(shù)支撐??丛创a是需要技術(shù)支撐的,不是隨便一個(gè)小白也能看懂的。沒有一些技術(shù)支撐,你頂多看看一小段,然后就看不下去,于是就放棄了。
缺乏正確心態(tài)??丛创a確實(shí)挺無聊的,如果大家心態(tài)沒放好,把它當(dāng)做一種任務(wù)去做,肯定覺得無聊,而且很容易放棄。
缺乏足夠時(shí)間。確實(shí)很忙,經(jīng)??戳艘徊糠趾?,天天加班,沒時(shí)間看,忙完后又忘了之前正在看的某某源碼。
個(gè)人建議
對(duì)于一般java程序員來說,閱讀源碼之前到底需要些什么技能呢?
個(gè)人建議,以下基礎(chǔ)知識(shí)必須會(huì)一些:
會(huì)設(shè)計(jì)模式:包括單例模式、工廠模式、代理模式、裝飾器模式、責(zé)任鏈模式、模板方法模式等。
會(huì)猜測(cè):大膽的猜測(cè),在看源碼的時(shí)候,多站在高層次想想,如果你是Mybatis的設(shè)計(jì)者,你會(huì)怎么設(shè)計(jì)?
會(huì)挑重點(diǎn)看:別被沒寫參數(shù)校驗(yàn)、類型校驗(yàn)等問題卡在那里。
會(huì)畫圖:流程圖、類圖等,找一些在線畫圖工具,媒體畫完就保存下來,如果中途一段時(shí)間不看了,再回頭看看這些圖,也能快速繼續(xù)。
Mybatis源碼分析
今天,我們就來看看Mybatis源碼的閱讀,具體舉個(gè)例子來看看:
案例和疑問
從我們最初的demo中開始:
- public static void main(String[] args) {
- String resource = "mybatis-config.xml";
- InputStream inputStream = null;
- SqlSession sqlSession = null;
- try {
- inputStream = Resources.getResourceAsStream(resource);
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- sqlSession = sqlSessionFactory.openSession();
- User user = sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectById", 1);
- System.out.println(user);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- inputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- sqlSession.close();
- }
- }
關(guān)于獲取數(shù)據(jù)流inputStream,這個(gè)我們就不討論了,我們主要關(guān)注重點(diǎn)。
對(duì)于上面demo,我們可以分成五個(gè)步驟:
第一步,創(chuàng)建一個(gè)工廠類sqlSessionFactory。
配置文件的解析就是在這里完成的。包括mybatis-config.xml和我們的Mapper.xml映射器文件。這一步我們關(guān)心的內(nèi)容是:解析的時(shí)候做了什么?產(chǎn)生了什么對(duì)象,解析的結(jié)果放在哪里的。因?yàn)檫@將意味著,我們后面使用的時(shí)候去哪里獲取這項(xiàng)配置項(xiàng)內(nèi)容。
第二步,通過SqlSessionFactory創(chuàng)建一個(gè)SqlSession。
那么問題來了,SqlSession中定義了各種增刪改查的API,是給客戶端調(diào)用,返回的是什么實(shí)現(xiàn)類?除了SqlSession以外,我們還創(chuàng)建了什么對(duì)象,創(chuàng)建了什么環(huán)境?
第三步,獲取到一個(gè)Mapper對(duì)象。
問題來了UserMapper.java是一個(gè)接口,并沒有為它創(chuàng)建實(shí)現(xiàn)類,那又是怎么被實(shí)例化的呢?我們使用的這個(gè)Mapper對(duì)象到底是什么對(duì)象呢?為什么要從SqlSession里去獲取呢?為什么傳進(jìn)去一個(gè)接口,然后還要用一個(gè)接口去接收呢?
第四步,調(diào)用接口方法。
問題是我們的接口沒有實(shí)現(xiàn)類,為什么就可以直接調(diào)用它的方法呢?那它調(diào)用的是誰的方法呢?是如何把SQL給關(guān)聯(lián)起來的呢?是如何獲取到數(shù)據(jù)的呢?
第五步,關(guān)閉相關(guān)資源。
開始源碼分析過程
由于涉及到內(nèi)容較多,下面就用幾張圖來展示整個(gè)流程。我們可以通過這幾張圖來快速翻閱Mybatis的源碼。
第一步
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
這一句代碼的整個(gè)流程如下:
根據(jù)inputStream,解析配置文件,創(chuàng)建出一個(gè)DefaultSqlSessionFactory默認(rèn)的SqlSessionFactory 實(shí)現(xiàn)類。構(gòu)建出一個(gè)工廠類,這個(gè)工廠類專門用來創(chuàng)建SqlSession對(duì)象的。
第二步
- SqlSession sqlSession = sqlSessionFactory.openSession();
獲取SqlSession的整個(gè)流程如下:
第三步
- User user = sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectById", 1);
第三步和第四步就是這行代碼畫的。
這一步是返回一個(gè)映射器代理類,映射器代理類專門用來給UserMapper接口和UserMapper.xml綁定的代理類。創(chuàng)建出來的代理類就可以實(shí)例化了,然后就可以調(diào)用UserMapper接口的方了。
第四步:調(diào)用代理對(duì)象執(zhí)行SQL的整個(gè)過程。
第五步,關(guān)閉資源。
希望大家按照這個(gè)流程,找點(diǎn)源碼看看。聽別人的看別人永遠(yuǎn)是別人的。
動(dòng)起來吧!
總結(jié)
其實(shí),沒什么好總結(jié)的。好好領(lǐng)悟一下為什么糾結(jié)吧!同時(shí)希望能看看我的建議,作為一個(gè)過來人,希望能幫助大家少走彎路。
最后,對(duì)于Mybatis源碼閱讀的整個(gè)流程,最好是本地環(huán)境搭起來,然后搞個(gè)demo,debug模式一步一步走起。
本文轉(zhuǎn)載自微信公眾號(hào)「 Java后端技術(shù)全?!?,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系 Java后端技術(shù)全棧公眾號(hào)。