原創作品,可以轉載,但是請標注出處地址:http://www.cnblogs.com/V1haoge/p/6625612.html
本應該先開始說Configuration配置類的,但是這個類有點過於復雜,因為MyBatis中的所有配置項全部在這個類中,可謂包羅萬象,一開始就討論如此高大上的東西,貌似有點不合適,認識和學習都應該從小開始,從基礎開始,所以我做了這樣一個小安排,先挑Configuration中重要的配置項進行了解,心中有了大概印象之后,在進行Configuration的解讀,這樣就能較為輕松的接受整個其中復雜的配置信息,而不至於不知所措。
首先我們來看看Environment——環境
先說說我們熟悉的內容,當我們單獨使用MyBatis框架時(不與Spring框架整合),是需要在Configuration.xml配置文件中進行環境配置的,其代碼如下:
1 <environments default="development"> 2 <environment id="development"> 3 <transactionManager type="JDBC"/> 4 <dataSource type="POOLED"> 5 <property name="driver" value="com.mysql.jdbc.Driver"/> 6 <property name="url" value="jdbc:mysql://localhost:3306/mbtest"/> 7 <property name="username" value="root"/> 8 <property name="password" value="123456"/> 9 </dataSource> 10 </environment> 11 </environments>
從上面的配置內容中可以看出,標簽environment代表的就是環境,其有一個屬性id,值為“development”(表示開發環境,對應的還會有生產環境),而在其下級節點還需要配置兩個內容:transactionManager和DataSource,前者是事務管理器,后者是數據源。“JDBC”表示事務管理器是JDBC類型了,這個標簽對應Configuration類創建時在其無參構造器中注冊的類型別名,通過這個類型別名注冊信息可以找到實際的JDBC事務工廠類:JdbcTransactionFactory(JDBC事務工廠,這個類之后會介紹到,稍安勿躁)。而數據源的類型為“POOLED”類型,同樣可以在Configuration類的無參構造器中找到對應的注冊信息:PooledDataSourceFactory(表示有連接池的數據源工廠,這個類之后也會介紹)。
而我們要介紹的Environment類就是這個environment標簽所代表的環境類,構建Configuration之前,第一步是進行類型別名注冊,第二步就是將Environment配置內容從配置文件中讀入Environment類中(這一步是在XMLConfigBuilder中完成的),並將其組合到Configuration類中。
Environment類位於org.apache.ibatis.mapping包下,整個類被final修飾,這意味着這個類是個最終類,就如String類一樣,是一個不可被更改的類,即其實例是唯一的不能被輕易修改。
下方列出Environment類的源碼
1 package org.apache.ibatis.mapping; 2 import javax.sql.DataSource; 3 import org.apache.ibatis.transaction.TransactionFactory; 4 /** 5 * 環境 6 * 決定加載哪種環境(開發環境/生產環境) 7 */ 8 public final class Environment { 9 //環境id 10 private final String id; 11 //事務工廠 12 private final TransactionFactory transactionFactory; 13 //數據源 14 private final DataSource dataSource; 15 public Environment(String id, TransactionFactory transactionFactory, DataSource dataSource) { 16 if (id == null) { 17 throw new IllegalArgumentException("Parameter 'id' must not be null"); 18 } 19 if (transactionFactory == null) { 20 throw new IllegalArgumentException("Parameter 'transactionFactory' must not be null"); 21 } 22 this.id = id; 23 if (dataSource == null) { 24 throw new IllegalArgumentException("Parameter 'dataSource' must not be null"); 25 } 26 this.transactionFactory = transactionFactory; 27 this.dataSource = dataSource; 28 } 29 //一個靜態內部類Builder 30 //建造模式 31 //用法應該是new Environment.Builder(id).transactionFactory(xx).dataSource(xx).build(); 32 public static class Builder { 33 private String id; 34 private TransactionFactory transactionFactory; 35 private DataSource dataSource; 36 public Builder(String id) { 37 this.id = id; 38 } 39 public Builder transactionFactory(TransactionFactory transactionFactory) { 40 this.transactionFactory = transactionFactory; 41 return this; 42 } 43 public Builder dataSource(DataSource dataSource) { 44 this.dataSource = dataSource; 45 return this; 46 } 47 public String id() { 48 return this.id; 49 } 50 public Environment build() { 51 return new Environment(this.id, this.transactionFactory, this.dataSource); 52 } 53 } 54 public String getId() { 55 return this.id; 56 } 57 public TransactionFactory getTransactionFactory() { 58 return this.transactionFactory; 59 } 60 public DataSource getDataSource() { 61 return this.dataSource; 62 } 63 }
通過源碼我們可以發現,在Environment類中有三個字段:id、transactionFactory、dataSource,分別對應於配置文件中的三個配置項(id、transactionManager、DataSource),而且這三項均為final類型,表示不可被更改,一次設置終身有效,所以在整個類中也只是使用三參構造器為三項字段賦值,而沒有set方法可以進行字段值的更改,只有get方法,可以獲取到設置的信息。
Environment類內部有一個靜態內部類Builder,這顯然是一個構建器類,所以Environgment實例的創建使用了構建者模式(也叫建造者模式)。我們當然可以直接使用外部類的構造器直接進行實例創建,但這並不是MyBatis推薦的(當然其實也不會要求你去手動創建Environgment實例,這里只是打個比方),MyBatis內部進行Environgment實例創建時,就是用其內部構建者進行創建,創建方式和源碼中注釋里一樣:
new Environment.Builder(id).transactionFactory(xx).dataSource(xx).build();
為什么要使用構建者模式呢?那讓我們來回憶一下構建者模式的內容。
構建者模式一般用於構建復雜對象時,將復雜對象分割成許多小對象進行分別構建,然后整合在一起形成一個大對象,這樣做能很好的規范對象構建的細節過程,這里也是一樣的目的,雖然說Environment類的字段較少,但在MyBatis中大量使用構建者模式的基礎上,在此處使用構建者模式也無可厚非,而且通過內部類的方式構建,這個Environment對象的創建會在內部類構建方法build()被顯式調用時才會在內存中創建,實現了懶加載。這又有點單例模式的意思在內,雖然Mybatis中可創建多個Environment環境,但是在正式運行時,只會存在一個環境,確實是使用內部類實現了懶加載的單例模式。
這個實例的創建最顯然的使用位置就是在XMLConfigBuilder構建器中解析構建Configuration類時在解析了Configuration.xml配置文件中environment標簽的內容之后,這個位置用於將讀自於配置文件的配置信息配置到了Environment對象中。(這句話有點拗口,不要着急,這個過程在以后介紹XMLConfigBuilder類時會有介紹的)
其實這個類很簡單,但它內部包含的TracsactionFactory和DataSource這兩個內容又是兩大塊內容,這一部分容后介紹。
自己理解的還很淺顯,希望隨着不斷的解讀源碼,能夠提升自己的認識,到時候再來這里進行進一步改進。
(未完待續)