mybatis 别名
1.别名的作用
别名是一个指代的名称,当类的全限定名过长的时候,我们可以用一个简短的名称指代它,这个名称可以再全文指代。
2.使用方式
别名的实现方式有三种
(1).指定一个类路径,并指定这个类的别名
(2).第二种方式,指定类名和别名
(3).指定一个包名,mybatis会自动扫描包下可以使用别名的类
3.源码分析
代码入口:typeAliasesElement(root.evalNode("typeAliases"));
typeAlias的加载方式,首先进入
(1).如果子节点是
调用configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage)方法
(2).如果子节点是
如果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())) {
// 加载方式
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) {
// 加载方式
typeAliasRegistry.registerAlias(clazz);
} else {
// 加载方式
typeAliasRegistry.registerAlias(alias, clazz);
}
} catch (ClassNotFoundException e) {
throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e);
}
}
}
}
}
分析别名的加载,三种情况
首先分析指定类路径,并指定这个类的别名的加载方式。原因是另外两种方法其实最后还是调用了这个方式
//alias != null
//
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> TYPE_ALIASES = new HashMap>();
//如果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
//
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);
}
//
String typeAliasPackage = child.getStringAttribute("name");
configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);
public void registerAliases(String packageName, Class> superType){
ResolverUtil> resolverUtil = new ResolverUtil>();
//查找此路径下所有的类
resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
//获取查找结果
Set>> 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);
}
}
}