史上最通俗易懂的Mybatis源碼分析之執行流程總結

一:Mybatis源碼分析流程

public static void main(String[] args) {

    try {
        // 基本mybatis環境
        // 1.定義mybatis_config文件地址
        String resources = "mybatis_config.xml";
        // 2.獲取InputStreamReaderIo流
        Reader reader = Resources.getResourceAsReader(resources);
        // 3.獲取SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        // 4.獲取Session
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 5.操做Mapper接口
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        UserEntity user = mapper.getUser(2);
        System.out.println(user.getName());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

總結:

一、讀取Mybatis配置文件信息sql

二、獲取SqlSessionFactory數據庫

a.使用XMLMappperBuilder解析Mybatis配置文件,封裝成Environment對象,再把Environment對象設置給Configuration對象;設計模式

b.調用ConfigurationElement函數,最終執行addMappedStatement方法,將mapper配置文件中的每一條SQL語句封裝成mappedStatement對象,做爲value保存在HashMap集合中;緩存

c.進入addLoaderResource方法,使用HashSet集合存放mybatis的mapper.xml 映射文件路徑地址;session

d.進入bindMapperForNamespace()方法,經過namespace使用Java反射機制找到mapper接口,再調用addMapper()方法,判斷是不是接口類型,是否註冊過(註冊過則拋出異常)其中mapperRegistry經過HashMap保存mapper接口,【key:接口;value:MapperProxyFactory】mybatis

三、獲取sessionapp

a.進入openSession()方法,執行newExecutor()方法建立執行器;函數

b.先建立 SimpleExecutor簡單執行器,再判斷是否開啓了二級緩存,默認是開啓的,就會去建立CacheExecutor緩存執行器,源碼分析

c.執行interceptorChain.pluginAll()方法,責任鏈設計模式,底層使用動態代理技術,使開發者能夠自定義插件開發,只須要實現Interceptor接口,並指定想要攔截的方法簽名便可,最後返回執行器;ui

四、操做mapper接口

a.調用getMapper()方法,最終執行mapperProxyFactory.newInstance(sqlSession)方法建立代理類MapperProxy;

b.當咱們調用mapper,getUser()方法的時候,就會去執行MapperProxy代理類的invoke()方法;

c.判斷mapper接口是否有實現類,顯然咱們沒有實現類,則調用cacheMapperMethod()方法去緩存中獲取要代理的方法method;

d.進入cacheMapperMethod()方法先去查找緩存中有沒有,沒有的話將mapper配置文件中配置的SQL語句和對應的mapper接口方法進行關聯並放入map緩存中,後期直接走緩存了,最後執行execute()方法;

e.執行execute()方法,最終調用selectOne()方法;

f.進入selectOne()方法,底層仍是查詢全部的,可是取第一個,查詢多個的話會拋出異常;

g.進入selectList()方法,調用getMapperStatement()方法獲取對應的SQL語句;

h.執行query()方法進行查詢,判斷若是開啓了二級緩存而且配置了二級緩存存儲介質(Redis,EhCache..)則先走二級緩存中查詢數據,第一次查詢是沒有緩存數據的,則刷新緩存配置,清除緩存。

i.二級緩存(sessionFactory)中沒有查詢到數據,就回去執行BaseExecutor去查詢 HashMap一級緩存中(sqlSession)是否有緩存數據,一級緩存(PerpetualCache)存放在內存中的,同理也是沒有的,最後查詢數據庫DB

j.將從數據庫查詢出來的數據緩存到一級緩存中,再把一級緩存中的數據同步到二級緩存,添加到二級緩存以前先添加到getTransactionalCache的entritiesToAddOnCommit的map集合中臨時緩存起來;

k.調用executor.close()方法循環迭代TransactionCache,最後將臨時map緩存數據提交到二級緩存中,若是事務回滾,則會將緩存數據清除掉

l.再次查詢的話,就有緩存了,會直接查詢到緩存數據返回,不會去查詢數據庫DB

版權:https://my.oschina.net/u/3995125

本文參考:螞蟻課堂http://www.mayikt.com

相關文章
相關標籤/搜索