前言
mybatis在处理parameterType(同resultType)属性时,通过设置@Alias注解或配置<typeAliases>标签后,就可以为类型别名和Java类型增加一种映射关系,从而在parameterType输入类型别名时,能获取到该Java类型。
那么,在我们没有设置如上两种配置,直接输入类名时,为什么也有可能通过这个类型别名获取到Java类型呢?
本文由该问题引出。
思路:
1. 大家熟知的设置类型别名的方式
2. parameterType将在何时使用类型别名
3. 这些类型别名又是如何添加映射关系的
4. parameterType使用类型别名的整个流程
类型别名的设置方式
下面是官方文档对类型别名的一些描述:
可以看到官方的文档中,主要由=@Alias注解和<typeAliases>来设置别名的,其实还有第三种隐含的设置。
1. 在mybatis-config.xml中设置<typeAliases>标签内容
2. 为mybatis.type-aliases-package包下的类里添加注解@Alias
3. yml中为mybatis.type-aliases-package设置包名后,会默认将该包下的类设置类型别名。
第三种方法文档没提到,源码中实现的,这也是为什么我们在没有设置前两项时,类型别名依旧生效的原因。OK,接下来就是源码的学习过程。
parameterType使用类型别名
在mybatis源码中,xml标签的所有内容会在解析后存放在MappedStatement类中,这个类通过XMLStatementBuilder#parseStatementNode创建,其中关于这两个属性的解析代码如下:
String parameterType = context.getStringAttribute("parameterType");
Class<?> parameterTypeClass = resolveClass(parameterType);
String resultType = context.getStringAttribute("resultType");
Class<?> resultTypeClass = resolveClass(resultType);
resolveClass则是获取Java类型的关键方法。而上面的方法BaseBuilder#resolveClass实际上是通过TypeAliasRegistry#resolveAlias将类型别名解析为Java类型的。
public <T> Class<T> resolveAlias(String string) {
try {
if (string == null) {
return null;
}
// issue #748
String key = string.toLowerCase(Locale.ENGLISH);
Class<T> value;
// 通过类型别名获取真实类型
if (typeAliases.containsKey(key)) {
value = (Class<T>) typeAliases.get(key);
} else {
// 通过全限定名获取
value = (Class<T>) Resources.classForName(string);
}
return value;
} catch (ClassNotFoundException e) {
throw new TypeException("Could not resolve type alias '" + string + "'. Cause: " + e, e);
}
}
获取Java类型的方式很简单,只有代码提到的两种:
1. 通过类型别名在别名字典中获取。
2. 通过类型的全限定名(例如java.lang.String)在类加载器中获取类型。
第二种方法无需多说,我们只需关注这个预设的类型别名字典就可以&