Mybatis中alices的实现

mybatis 别名
1.别名的作用
别名是一个指代的名称,当类的全限定名过长的时候,我们可以用一个简短的名称指代它,这个名称可以再全文指代。
2.使用方式
别名的实现方式有三种
(1).指定一个类路径,并指定这个类的别名

<typeAliases>
    <typeAlias alias="Users" type="com.dzy.mybatis.model.Users"/>
</typeAliases>

(2).第二种方式,指定类名和别名

<typeAliases>
    <typeAlias type="com.dzy.mybatis.model.Card"/>
</typeAliases>

(3).指定一个包名,mybatis会自动扫描包下可以使用别名的类

<typeAliases>
    <package name="com.dzy.mybatis.model" />
</typeAliases>

3.源码分析
<typeAliases>的加载过程
代码入口:typeAliasesElement(root.evalNode("typeAliases"));

typeAlias的加载方式,首先进入<typeAliases>标签后,先判断子节点。
(1).如果子节点是<package>,
调用configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage)方法
(2).如果子节点是<typeAlias>,判断type的内容
如果type为null,调用typeAliasRegistry.registerAlias(clazz);
如果type不为null,调用typeAliasRegistry.registerAlias(alias, clazz)

private void typeAliasesElement(XNode parent) {
    if (parent != null) { 
        //获取所有的子节点
      for (XNode child : parent.getChildren()) {
        if ("package".equals(child.getName())) {
          //<package name="" />加载方式
          String typeAliasPackage = child.getStringAttribute("name");
          configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);
        } else {
          // 获取 alias 和 type 属性值,alias可为空
          String alias = child.getStringAttribute("alias");
          String type = child.getStringAttribute("type");
          try {
            // 加载 type 对应的类型
            Class<?> clazz = Resources.classForName(type);
            if (alias == null) {
            //<typeAlias type=""/>加载方式
              typeAliasRegistry.registerAlias(clazz);
            } else {
            //<typeAlias alias="" type=""/>加载方式
              typeAliasRegistry.registerAlias(alias, clazz);
            }
          } catch (ClassNotFoundException e) {
            throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e);
          }
        }
      }
    }
    }

分析别名的加载,三种情况
首先分析指定类路径,并指定这个类的别名的加载方式。原因是另外两种方法其实最后还是调用了这个方式
<typeAlias alias="Users" type="com.dzy.mybatis.model.Users"/>
//alias != null
//<typeAlias alias="Users" type="com.dzy.mybatis.model.Users"/>
typeAliasRegistry.registerAlias(alias, clazz);

public void registerAlias(String alias, Class<?> value) {
if (alias == null) throw new TypeException("The parameter alias cannot be null");
//将Alias的值大写转换为小写
String key = alias.toLowerCase(Locale.ENGLISH); // issue #748
//TYPE_ALIASES的定义:  
//private final Map<String, Class<?>> TYPE_ALIASES = new HashMap<String, Class<?>>();
//如果TYPE_ALIASES中存在,抛出异常,否则,放入到TYPE_ALIASES中
if (TYPE_ALIASES.containsKey(key) && TYPE_ALIASES.get(key) != null && !TYPE_ALIASES.get(key).equals(value)) {
  throw new TypeException("The alias '" + alias + "' is already mapped to the value '" + TYPE_ALIASES.get(key).getName() + "'.");
}
TYPE_ALIASES.put(key, value);

}

//alias == null
//<typeAlias type="com.dzy.mybatis.model.Card"/>
typeAliasRegistry.registerAlias(clazz);
//处理思路是通过type获取类名,然后调用registerAlias(alias, type)方法

public void registerAlias(Class<?> type) {
//获取全路径类名的简称
String alias = type.getSimpleName();
Alias aliasAnnotation = type.getAnnotation(Alias.class);
if (aliasAnnotation != null) {
  // 从注解中取出别名
  alias = aliasAnnotation.value();
} 
//调用registerAlias方法
registerAlias(alias, type);

}

//<package name="com.dzy.mybatis.model" />
String typeAliasPackage = child.getStringAttribute("name");
configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);

public void registerAliases(String packageName, Class<?> superType){
    
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
//查找此路径下所有的类
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)
  // Skip also inner classes. See issue #6
  // 忽略接口,内部类,匿名类
  if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
    // 为类型注册别名
    registerAlias(type);
  }
}

}

相关推荐