zoukankan      html  css  js  c++  java
  • 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对象内建别名,详细情况可直接看源代码。

  • 相关阅读:
    VS2013快速安装教程
    软件工程课程的感想
    GitHub和Microsoft TFS对比有什么优势
    拼接素数
    C语言程序题
    vue中的实例方法的底层原理
    ios 安卓
    防抖
    伪数组转真数组的放法
    http和https的一种能力?
  • 原文地址:https://www.cnblogs.com/sunzhenchao/p/3010527.html
Copyright © 2011-2022 走看看