• 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这两个内容又是两大块内容,这一部分容后介绍。

      自己理解的还很浅显,希望随着不断的解读源码,能够提升自己的认识,到时候再来这里进行进一步改进。

      (未完待续)

  • 相关阅读:
    【2】通过Ajax方式上传文件(图片),使用FormData进行Ajax请求
    【1】mongoDB 的安装及启动
    第一篇博客
    Java Integer 进制转化的实现(附源码),对模与补码的理解
    筛法求素数(普通筛法与欧拉筛法) 这是个问题
    字典的拼接方法
    使用Selenium抓取百度指数一
    正则表达式30分钟入门教程
    微博抓取尝试
    __call__方法的最简要说明
  • 原文地址:https://www.cnblogs.com/V1haoge/p/6625612.html
Copyright © 2020-2023  润新知