MyBatis源碼解析(二)——Environment環境


原創作品,可以轉載,但是請標注出處地址: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這兩個內容又是兩大塊內容,這一部分容后介紹。

  自己理解的還很淺顯,希望隨着不斷的解讀源碼,能夠提升自己的認識,到時候再來這里進行進一步改進。

  (未完待續)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM