在使用mybatis框架時,第一步就需要產生SqlSessionFactory類的實例(相當於是產生連接池),通過調用SqlSessionFactoryBuilder類的實例的build方法來完成。下面具體對這一過程涉及的源碼進行分析。
首先用Eclipse工具查看SqlSessionFactoryBuilder類的Outline視圖:
從上圖中可以看出,SqlSessionFactoryBuilder類負責構建SqlSessionFactory,並且提供了多個build的重載方法。但其實很多都是在調同一簽名的方法,例如:
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) ,只是由於方法參數environment和 propertiese都可以為null,
所以為了提供調用的便利性,才提供了下面的三個方法:
public SqlSessionFactory build(InputStream inputStream) public SqlSessionFactory build(InputStream inputStream, String environment) public SqlSessionFactory build(InputStream inputStream, Properties properties)
按照上述思路去除重復的,真正的重載方法只有如下三種:
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) public SqlSessionFactory build(Reader reader, String environment, Properties properties) public SqlSessionFactory build(Configuration config)
可以看出,配置信息可以以三種形式提供給SqlSessionFactory的build方法,分別是InputStream(字節流)、Reader(字符流)、Configuration(類),由於字節流與字符流都屬於讀取配置文件的方式,所以從配置信息的來源就很容易想到構建一個SqlSessionFactory有兩種方式,大致代碼如下:
(1) 讀取xml文件構造方式
String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream) ;
(2) 編程構造方式
DataSource dataSource = BlogDataSourceFactory.getBlogDataSource(); TransactionFactory transactionFactory = new JdbcTransactionFactory(); Environment environment = new Environment("development", transactionFactory, dataSource); Configuration configuration = new Configuration(environment); configuration.addMapper(BlogMapper.class); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration) ;
下面先來分析XML文件構造方式的build方法的源碼:
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); 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. } } }
通過上面這幾行代碼,就能看出基於XML文件的這種構造方式,通過從XML中讀取信息的工作之后,也是構造出Configuration對象之后再繼續進行SqlSessionFactory的構建工作的,只是多了些XML的解析工作,所以我們只需單刀直入,直按分析編程構造方式的代碼就可以了,或者是直接分析 build(parser.parse())這句代碼(參數產生過程先跳過)
編程構造方式的build方法源碼如下(基於xml的構造方式的build(parser.parse())最終也是調了這個代碼):
public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }
其實這么看來SqlSessionFactory在mybatis的默認實現類為org.apache.ibatis.session.defaults.DefaultSqlSessionFactory , 其構造過程主要是注入了Configuration的實例對象,Configuration的實例對象即可通過解析xml配置文件產生,也可能通過代碼直接構造。以上代碼使用了一個設計模式:建設者模式(Builder),SqlSessionFactoryBuilder扮演具體的建造者,Configuration類則負責建造的細節工作,SqlSession則是建造出來的產品。
以下是類圖和建造者模式的基本形態圖,讀者自行對照閱讀。
構造者模式是一種對象的創建模式。它可以將一個復雜對象的內部構成特征與對象的構建過程完全分開。