Mybatis源代碼分析之別名


在我們平時寫sql時為了簡化書寫,方便理解記憶會經常用到別名,比如一個表名很長可以直接取別名a就可以代替,還有比如你查詢出來的結果有的字段很長不是通俗叫法,我們可以取你想要的字段名。別名的好處是顯而易見的,mybatis把這個好處也擴展到了類上。

官網(http://mybatis.github.io/mybatis-3/configuration.html#typeAliases)有雲:

A type alias is simply a shorter name for a Java type. It's only relevant to the XML configuration and simply exists to reduce redundant typing of fully qualified classnames.

別名類型只是一個java類型的縮寫名。它只和XML配置文件相關,它存在的目的是為了減少全路徑類名的輸入。在mybatis的配置文件中有兩種定義方式:

<typeAliases>
 <!--  指定一個具體的類的別名 -->
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
 <!--  指定一個包中所有類的別名,后面會講到mybatis是如何注冊這個包里的類 -->
  <package name="domain.blog"/>
</typeAliases>

從官網上可以看到,mybatis對常用的java類型都內建了別名。

 

言歸正傳,我們開始看看mybatis是如何實現別名功能的,這回涉及到一個類和一個注解。

一、TypeAliasRegistry

TypeAliasRegistry類位於org.apache.ibatis.type包(關於這個包更多的介紹可以參考 http://www.cnblogs.com/sunzhenchao/archive/2013/04/09/3009431.html),別名相關的功能都在類中完成,我們先看看這個類包含的屬性:

private final HashMap<String, Class> TYPE_ALIASES = new HashMap<String, Class>();

這個map的key類型是String,value類型是Class。key就是這個類的別名。

在了解完這個類的屬性之后,我們再了解下mybatis是如何注冊別名的。

1、注冊一個類的別名

我們先看如何將一個類的別名注冊到mybatis中的,即如何解析mybatis配置文件中的

<typeAlias alias="Author" type="domain.blog.Author"/>

這個文本元素。

public void registerAlias(String alias, Class value) {
    assert alias != null;
   // 把別名轉為小寫字母
    String key = alias.toLowerCase();
   // 如果key或者alias如果已經添加到了map中,且對應的class和已添加的不一致則拋出異常
    if (TYPE_ALIASES.containsKey(key) && !TYPE_ALIASES.get(key).equals(value.getName()) && TYPE_ALIASES.get(alias) != null) {
      if (!value.equals(TYPE_ALIASES.get(alias))) {
        throw new TypeException("The alias '" + alias + "' is already mapped to the value '" + TYPE_ALIASES.get(alias).getName() + "'.");
      }
    }
    // 否則添加到map中
    TYPE_ALIASES.put(key, value);
  }

 

2、注冊一個包中所有類的別名

首先需要把這個包中所有的類都找到,然后再進行注冊。將這個包所有的類都讀到內存中用到的函數為:

public void registerAliases(String packageName){
    // 第二個會在mybatis的io去尋找對應的類時會用到
    // 因為是把這個包中所有的類都進行別名注冊,因而用的的Object類
    registerAliases(packageName, Object.class);
  }

  public void registerAliases(String packageName, Class superType){
    ResolverUtil<Class> resolverUtil = new ResolverUtil<Class>();
    // mybatis的io去包中尋找對應的類,因為是把這個包中所有的類都進行別名注冊
    // 因而此時會將所有的類都讀到
    resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
    Set<Class<? extends Class>> typeSet = resolverUtil.getClasses();
    for(Class type : typeSet){
      //Ignore inner classes and interfaces (including package-info.java)
      // 忽略內部類和接口
      if (!type.isAnonymousClass() && !type.isInterface()) {
        registerAlias(type);
      }
    }
  }

前面是讀到所有的類,現在開始進行注冊:

public void registerAlias(Class type) {
    // 利用反射機制得到這個類的不包含包名的簡單名稱
    String alias = type.getSimpleName();
    // 如果這個類有Alias這個注解,獲取這個注解的值作為別名,否則就用自己的原始類名
    Alias aliasAnnotation = (Alias) type.getAnnotation(Alias.class);
    if (aliasAnnotation != null) {
      alias = aliasAnnotation.value();
    } 
    // 開始注冊,這個步驟在上一小節有講,不再進行重復
    registerAlias(alias, type);
  }

 

二、別名功能初始化

前面提到mybatis中已經對許多常用的java對象內建了別名,那么這些別名是什么時候又是如何加載到mybatis中呢?

我們還要回到mybatis的Configuration類,這個類包含了mybatis的各種各樣的配置,別名的配置也在其中,Configuration類包含了一個屬性:

protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();

而在TypeAliasRegistry類的構造函數中會為常用的java對象內建別名,詳細情況可直接看源代碼。


免責聲明!

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



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