深入源碼分析mybatis查詢原理(二)

在上一篇博文已經把項目給構建完畢了,接下來就要乾點正事了

先分析一次查詢,看看mybatis都幹了什麼,代碼:


上述代碼其實mybatis 代碼經歷了mybatis初始化 -->創建SqlSession -->執行SQL語句 返回結果三個過程。

1.mybatis初始化的初始化過程---即讀取到xml配置文件解析成一個Configuration對象的過程。

mybatis初始化,其實mybatis通過加載mybatis的配置文件創建一個Configuration對象


上圖是從網上找到的,從圖中可以看出這個Configuration對像就是維護者mybatis的配置文件信息,我們可以從源碼中看到


這是由SqlSessionFactoryBuilder把讀到的資源解析成一個Configuration對象。對應於代碼就發生在這句話中:SqlSessionFactory factory = builder.build(reader);至於怎麼把配置文件變成XNode對象這是屬於xml解析的範疇,這裏不在多說。

下面從網上盜一張圖,更好的理解SqlSessionFactory 創建過程


接下來我們看看SqlSessionFactory怎麼通過得到的Configuration創建一個SqlSession

2.SqlSession的創建

我們跟蹤 SqlSession session = factory.openSession();代碼,可以找到如下的代碼


我們從這段代碼中可以瞭解到創建SqlSession的過程中做了如下的操作

(1) 創建了TransactionFactory 而且我們可以從Variables中看到是jdbcTransactionFactory,爲什麼是這個?跟蹤getTransactionFactoryFromEnvironment()方法,代碼如下:


發現如果我們沒有配置,默認的事物工廠是ManagedTransactionFactory,而這裏是jdbcTransactionFactory,是因爲我們在配置文件中有這麼一個配置<transactionManager type="JDBC"></transactionManager>

(2)接着創建Executor(這個如何創建,爲什麼創建的是CachingExecutor,我會把這個放在mybatis緩存中討論)

(3)創建DefaultSqlSession。

以上Sqlsession創建完成。

3.執行sql語句放到下一章討論,在討論執行sql語句之前,先來mybatis如何處理我們寫的mapper接口

我們知道接口是不能實例化和執行方法的,那麼mybatis怎麼處理我們的接口呢,我們寫的方法怎麼被調用的呢,原因在於mybatis對我們的接口做的代理


可以看到這個empmapper是個代理,那麼它是如何創建代理的呢,又是用了什麼代理呢,看源碼:

session.getMapper();

@Override
  public <T> T getMapper(Class<T> type) {
    return configuration.<T>getMapper(type, this);
  }
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
  }
@SuppressWarnings("unchecked")
  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }

這裏knownMappers是一個Map,類型Map<Class<?>, MapperProxyFactory<?>>,也就是說,這個map把我們寫的Mapper接口類作爲key,放入對應的MapperProxyFactory。然後通過這個MapperProxyFactory創建出代理對象

 @SuppressWarnings("unchecked")
  protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

  public T newInstance(SqlSession sqlSession) {
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }
這裏我們還能看出這是基於jdk的動態代理模式

下一篇討論mybatis查詢

如果有讀者發現我說的有不對的地方,還望大家多多指教!




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