SqlSessionFactory開始創建
根據上一節我們知道,使用Mybatis時,操作過程如下:
- 根據配置文件使用
SqlSessionFactoryBuilder
創建SqlSessionFactory
- 使用
SqlSessionFactory
獲取一個SqlSession
- 通過
SqlSession
獲取XXXMapper
對象 - 最後通過獲取到的
XXXMapper
對象調用我們在配置文件中聲明的方法。
根據Mybatis的例子中,我們可以按照如下代碼創建一個SqlSessionFactory:
// 指定配置文件位置
String resource = "org/mybatis/example/mybatis-config.xml";
// 獲取配置文件文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 通過SqlSessionFactoryBuilder使用配置文件創建一個`SqlSessionFactory`
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
經過了這一步 SqlSessionFactory
就創建完成了,那麼我們可以先考察一下創建完成的SqlSessionFactory
到底是什麼樣子的?事實上SqlSessionFactory是一個接口,
在Mybatis中有兩個具體實現,分別是SqlSessionManager
和DefaultSqlSessionFactory
。
這裏筆者先劇透一下,現在我們主要考察DefaultSqlSessionFactory
類,先不管SqlSessionManager
。
考察DefaultSqlSessionFactory
可以看到該類只有一個屬性:
private final Configuration configuration;
屬性名爲configuration
(配置),這就是我們在配置文件中寫的配置,全部都存儲在這一個對象中。所以SqlSessionFactoryBuilder
就解析了一個配置?
實際上是的,SqlSessionFactoryBuilder
就解析了一個配置,它將配置文件中所有的配置都存儲到了Configuration
對象中。
其實這種操作並不罕見,拿離我們最近的Java來說,我想正在讀這篇文章的你一定使用過Java,我們寫的代碼都是.java
文件,這些文件會編譯成字節碼文件
,這些字節碼文件都會加載到內存中,最後成爲一個個Class對象。Spring 中的Bean配置的xml文件也是同理。所以這是一個基本操作。每種配置文件都有一種解析方式,正是如此,使得配置文件與配置對象通過配置解析器解耦。
如下圖:
每個配置解析器都只做一件事,就是將配置文件解析成存儲配置的Configuration對象,這也符合了單一職責原則。這也算是一個工廠模式的實現吧,將具體的配置實現與配置對象解耦。不過這個工廠模式不限於只在代碼處實現,因爲配置文件也是它的一部分。
所以,Mybatis、Spring等一系列框架既有Xml文件配置、也有Java配置,甚至有的有yaml文件配置,都是因爲這個原因。
那麼接下來讓我們查看SqlSessionFactoryBuilder
解析配置文件的邏輯,即SqlSessionFactoryBuilder
的build(InputStream)
方法:
public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
}
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
// 創建XML文件配置解析器
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
// 解析XML文件,並根據解析結果創建DefaultSqlSessionFactory
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
可以看到所有的xml文件配置解析都封裝在了XMLConfigBuilder
中。
通過上述的分析我們知道了,SqlSessionFactoryBuilder
僅僅通過XMLConfigBuilder
解析了XML文件的配置,並存儲在Configuration
對象中 ,最後通過Configuration
對象創建一個DefaultSqlSessionFactory
。
總結
通過分析SqlSessionFactoryBuilder
,個人覺得這個類設計的並不是很好,因爲它將解析方式和 FactoryBuilder
耦合了起來,使用SqlSessionFactoryBuilder
就只能使用xml文件來配置Mybatis。如果想擴展其他方式就只能自己重寫一個FactoryBuilder
。