首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

MyBatis 源碼解析 8:TypeAliasRegistry 類型別名註冊器核心原理

     編輯:Java 綜合教學

MyBatis 源碼解析 8:TypeAliasRegistry 類型別名註冊器核心原理

類型別名的作用

在 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);
}

兩種使用者自定義註冊方式

1. 包掃描註冊 (XML: <package name="..."/>)

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);
}

2. 逐個註冊 (XML: <typeAlias type="..." alias="..."/>)

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 類型系統雙引擎

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved