先放一張圖,讓大家簡單認識一下:
1、解析xml的時候
首先,Mybatis在初始化SqlSessionFactoryBean
的時候,找到mapperLocations
路徑去解析裏面所有的XML文件
2、創建sqlsource
Mybatis會把每個SQL標籤封裝成SqlSource對象。然後根據SQL語句的不同,又分爲動態SQL和靜態SQL。其中,靜態SQL包含一段String類型的sql語句;而動態SQL則是由一個個SqlNode組成
3、創建mappedStatement
XML文件中的每一個SQL標籤就對應一個MappedStatement對象,這裏面有兩個屬性很重要。
id
全限定類名+方法名組成的ID。
sqlSource
當前SQL標籤對應的SqlSource對象。
創建完MappedStatement對象,將它緩存到Configuration#mappedStatements中。
Configuration對象,我們知道它就是Mybatis中的大管家,基本所有的配置信息都維護在這裏。把所有的XML都
解析完成之後,Configuration就包含了所有的SQL信息。
到目前爲止,XML就解析完成了。看到上面的圖示,聰明如你,也許就大概知道了。當我們執行Mybatis方法的時
候,就通過全限定類名+方法名找到MappedStatement對象,然後解析裏面的SQL內容,執行即可。
4、dao接口代理
你的項目是基於SpringBoot的,那麼肯定也見過這種:
@MapperScan("com.xxx.dao")
它們的作用是一樣的。將包路徑下的所有類註冊到Spring Bean中,並且將它們的beanClass設置爲
MapperFactoryBean。有意思的是,MapperFactoryBean實現了FactoryBean接口,俗稱工廠Bean。那麼,當我
們通過@Autowired注入這個Dao接口的時候,返回的對象就是MapperFactoryBean這個工廠Bean中的
getObject()方法對象。
那麼,這個方法幹了些什麼呢?
簡單來說,它就是通過JDK動態代理,返回了一個Dao接口的代理對象,這個代理對象的處理器是MapperProxy對
象。所有,我們通過@Autowired注入Dao接口的時候,注入的就是這個代理對象,我們調用到Dao接口的方法時,
則會調用到MapperProxy對象的invoke方法。
5、執行
當我們調用Dao接口方法的時候,實際調用到代理對象的invoke方法。
在這裏,實際上調用的就是SqlSession裏面的東西了
public class DefaultSqlSession implements SqlSession {
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
return executor.query(ms,
wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
}
}
}
它就是通過statement全限定類型+方法名拿到MappedStatement 對象,然後通過執行器Executor去執行具體SQL並返回