最近工作不忙,上班時間看了下 mybatis 源碼,學習學習…
我們要使用 mybatis,就必須得有 SqlSession 對象,它是 mybatis 的核心接口,它提供了執行 sql 、獲取 mapper 和管理事物的功能。而想要得到 SqlSession 對象。從源碼可知 SqlSession 是一個接口,並不能直接 new 出來,那麼肯定就有實現類讓我們使用,而 mybatis 確實也提供了對它的一個默認實現 DefaultSqlSession,它的源碼如下:
public class DefaultSqlSession implements SqlSession {
private Configuration configuration;
// Sql 執行器
private Executor executor;
private boolean autoCommit;
private boolean dirty;
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
this.configuration = configuration;
this.executor = executor;
this.dirty = false;
this.autoCommit = autoCommit;
}
public DefaultSqlSession(Configuration configuration, Executor executor) {
this(configuration, executor, false);
}
// 其它是對 sql 操作方法,不列舉
}
從上述源碼可以知道,如果直接通過 new 的方式創建 SqlSession 對象,就需要自己構造 Configuration 和 Executor 對象,而以硬編碼方式創建 Configuration 對象比較麻煩。因此 mybatis 提供了通過 SqlSessionFactory 工程來獲取 SqlSession 對象,所以下面主要分析下 SqlSessionFactory 對象的創建過程。
SqlSessionFactory 工廠對象提供了幾個重載的 build() 方法來創建 SqlSessionFactory 對象,我們就拿這其中的一個進行分析。
如上圖所示,其中核心代碼已圈紅,XMLConfigBuilder 對象是準備好解析 xml 配置文件的工具,真正解析 xml 配置文件的是 XMLConfigBuilder 的 parser() 方法。
parse() 方法會首先判斷 xml 文件是否已被解析,感覺這個方法非線程安全的,如果多線程調用這個方法,可能都會執行 parserConfiguration() 方法。接下來就是通過 parseConfiguration() 方法解析 xml 文件中的各個元素,從如下源碼中可以看出,每個元素對應一個解析方法,所有解析的內容之後都會作爲 Configuration 對象的成員變量,其中最重要的元素解析方法是 mapperElement() 方法。
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
對 xml 配置文件解析完之後,返回 Configuration 對象,此對象包含了所有 mybatis 運行的配置信息,然後生成 DefaultSqlSessionFactory 對象。
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
至此,創建 SqlSessionFactory 對象的過程就完了,整個流程還是比較簡單清晰明瞭的。最後附上整個流程的時序圖: