在 Mapper XML 中配置 parameterType、resultType 時使用簡短別名 (如 int、User) 替代全限定名 (java.lang.Integer、com.xxx.User),MyBatis 解析時透過 TypeAliasRegistry.resolveAlias() 轉換為實際 Class 物件。
public TypeAliasRegistry() {
// 字串
registerAlias("string", String.class);
// 包裝類型
registerAlias("byte", Byte.class); ... registerAlias("boolean", Boolean.class);
registerAlias("int", Integer.class); registerAlias("integer", Integer.class);
// 陣列包裝類型
registerAlias("int[]", Integer[].class); ...
// 基本類型 (前綴 _)
registerAlias("_int", int.class); registerAlias("_int[]", int[].class); ...
// 日期/數字/物件
registerAlias("date", Date.class); registerAlias("bigdecimal", BigDecimal.class);
registerAlias("object", Object.class); ...
// 集合
registerAlias("map", Map.class); registerAlias("list", List.class);
registerAlias("hashmap", HashMap.class); registerAlias("arraylist", ArrayList.class);
// 其他
registerAlias("ResultSet", ResultSet.class);
}
private final Map<String, Class<?>> TYPE_ALIASES = new HashMap<>();
public void registerAlias(String alias, Class<?> value) {
if (alias == null) throw new TypeException("alias cannot be null");
String key = alias.toLowerCase(Locale.ENGLISH); // 不區分大小寫
if (TYPE_ALIASES.containsKey(key)
&& TYPE_ALIASES.get(key) != null
&& !TYPE_ALIASES.get(key).equals(value)) {
throw new TypeException("Alias '" + alias + "' already mapped to " + TYPE_ALIASES.get(key).getName());
}
TYPE_ALIASES.put(key, value);
}
public void registerAliases(String packageName) {
registerAliases(packageName, Object.class); // 不限制父類型
}
public void registerAliases(String packageName, Class<?> superType) {
ResolverUtil<Class<?>> resolver = new ResolverUtil<>();
resolver.find(new ResolverUtil.IsA(superType), packageName);
for (Class<?> type : resolver.getClasses()) {
// 排除匿名類、介面、內部類、package-info
if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
registerAlias(type);
}
}
}
public void registerAlias(Class<?> type) {
String alias = type.getSimpleName(); // 預設類名首字母小寫
Alias annotation = type.getAnnotation(Alias.class);
if (annotation != null) alias = annotation.value(); // @Alias("customName")
registerAlias(alias, type);
}
public void registerAlias(String alias, String value) {
try {
registerAlias(alias, Resources.classForName(value));
} catch (ClassNotFoundException e) {
throw new TypeException("Error registering type alias " + alias, e);
}
}
public <T> Class<T> resolveAlias(String string) {
if (string == null) return null;
String key = string.toLowerCase(Locale.ENGLISH);
Class<T> value;
if (TYPE_ALIASES.containsKey(key)) {
value = (Class<T>) TYPE_ALIASES.get(key);
} else {
// 允許直接傳全限定名字串
value = (Class<T>) Resources.classForName(string);
}
return value;
}
TypeAliasRegistry 是 Configuration 核心組件之一,Mapper 解析階段 (XMLMapperBuilder) 大量調用 resolveAlias() 將 XML 字串轉為 Class,再交給 TypeHandlerRegistry 進行 JDBC/Java 類型轉換。
別名註冊器 + 類型處理器註冊器 = MyBatis 類型系統雙引擎