Mybatis系列三:类型别名、类型解析器的注册

TypeAlias可以帮助我们在Mybatis配置文件中直接引用类别名,而不必使用类完全限定名那么冗长的名字。TypeAliasRegistry、Configuration实例化时会注册默认的类别名,方便我们使用。类别名忽略大小写,在注册类别名或根据类别名或去类时,Mybatis会将别名转换成小写。

TypeHandlerRegistry帮助我们将Java类型和数据库类型进行转换。一个Java类型可以对应多个数据库类型。

 

一、TypeAliasRegistry

注册类别名或根据别名获取类都会将别名转成小写,TypeAliasRegistry实例化时会注册常用类别名。

 

1.1 扫描指定包下类注册别名

public void registerAliases(String packageName){

   registerAliases(packageName, Object.class);

 }

 

 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){

     // 忽略内部类、接口、抽象类(包括package-info.java)

     if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {

       registerAlias(type);

     }

   }

 }

 

1.2 注册类别名

public void registerAlias(Class type) {

   // 获取类名

   String alias = type.getSimpleName();

   // 获取类上的@Alias注解

   Alias aliasAnnotation = type.getAnnotation(Alias.class);

   if (aliasAnnotation != null) {

     alias = aliasAnnotation.value();

   }

   registerAlias(alias, type);

 }

 

1.3 保存别名(转成小写)和类映射关系

// value若为NULL,后续相同别名的会被覆盖。如果没有获取时返回NULL,需要注意处理。

public void registerAlias(String alias, Class value) {

   if (alias == null) {

     throw new TypeException("The parameter 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("The alias '" + alias + "' is already mapped to the value '" + TYPE_ALIASES.get(key).getName() + "'.");

   }

   TYPE_ALIASES.put(key, value);

 }

 

1.4 根据别名(转成小写)获取类

public Class resolveAlias(String string) {

   try {

     if (string == null) {

       return null;

     }

     // 别名转成小写

     String key = string.toLowerCase(Locale.ENGLISH);

     Class value;

     if (TYPE_ALIASES.containsKey(key)) {

       value = (Class) TYPE_ALIASES.get(key);

     } else {

       value = (Class) Resources.classForName(string);

     }

     return value;

   } catch (ClassNotFoundException e) {

     throw new TypeException("Could not resolve type alias '" + string + "'.  Cause: " + e, e);

   }

 }

二、TypeHandlerRegistry

2.1 根据JavaType(如果存在)获取typeHandler实例 getInstance

public TypeHandler getInstance(Class javaTypeClass, Class typeHandlerClass) {

   if (javaTypeClass != null) {

     try {

  // 需要Java类型参数

       Constructor c = typeHandlerClass.getConstructor(Class.class);

       return (TypeHandler) c.newInstance(javaTypeClass);

     } catch (NoSuchMethodException ignored) {

       // ignored

     } catch (Exception e) {

       throw new TypeException("Failed invoking constructor for handler " + typeHandlerClass, e);

     }

   }

   try {

     Constructor c = typeHandlerClass.getConstructor();

     return (TypeHandler) c.newInstance();

   } catch (Exception e) {

     throw new TypeException("Unable to find a usable constructor for " + typeHandlerClass, e);

   }

 }

 

2.2 根据typeHandlerClass注册类型处理器

// 获取typeHandler Class上的@MappedTypes(Java类型)

public void register(Class typeHandlerClass) {

   boolean mappedTypeFound = false;

   // 获取typeHandler Class上的@MappedTypes(Java类型)

   MappedTypes mappedTypes = typeHandlerClass.getAnnotation(MappedTypes.class);

   if (mappedTypes != null) {

     for (Class javaTypeClass : mappedTypes.value()) {

  // 传送门:5.3

       register(javaTypeClass, typeHandlerClass);

       mappedTypeFound = true;

     }

   }

 

   // 没有@MappedType即没有指定Java类型

   if (!mappedTypeFound) {

     // 传送门:5.4

     register(getInstance(null, typeHandlerClass));

   }

 }

 

2.3 根据Java类型、typeHandlerClass注册类型处理器

public void register(Class javaTypeClass, Class typeHandlerClass) {

   // 传送门:5.5

   register(javaTypeClass, getInstance(javaTypeClass, typeHandlerClass));

 }

 

2.4 根据typeHandler实例注册类型处理器

public void register(TypeHandler typeHandler) {

   boolean mappedTypeFound = false;

   // 获取typeHandler 实例上的@MappedTypes(Java类型)

   MappedTypes mappedTypes = typeHandler.getClass().getAnnotation(MappedTypes.class);

   if (mappedTypes != null) {

     for (Class handledType : mappedTypes.value()) {

  // 传送门:5.5

       register(handledType, typeHandler);

       mappedTypeFound = true;

     }

   }

   // @since 3.1.0 - try to auto-discover the mapped type

   if (!mappedTypeFound && typeHandler instanceof TypeReference) {

     try {

       TypeReference typeReference = (TypeReference) typeHandler;

       register(typeReference.getRawType(), typeHandler);

       mappedTypeFound = true;

     } catch (Throwable t) {

       // maybe users define the TypeReference with a different type and are not assignable, so just ignore it

     }

   }

   if (!mappedTypeFound) {

     // 传送门:5.5

     register((Class) null, typeHandler);

   }

 

2.5 根据Java类型、typeHandler实例注册类型处理器

private void register(Type javaType, TypeHandler typeHandler) {

   // 获取typeHandler 实例上的@MappedJdbcTypes(JDBC类型)

   MappedJdbcTypes mappedJdbcTypes = typeHandler.getClass().getAnnotation(MappedJdbcTypes.class);

   if (mappedJdbcTypes != null) {

     for (JdbcType handledJdbcType : mappedJdbcTypes.value()) {

  // 传送门:5.6

       register(javaType, handledJdbcType, typeHandler);

     }

     if (mappedJdbcTypes.includeNullJdbcType()) {

  // 传送门:5.6

       register(javaType, null, typeHandler);

     }

   } else {

// 传送门:5.6

     register(javaType, null, typeHandler);

   }

 }

 

2.6 根据Java类型、JDBC类型、typeHandler实例注册类型处理器

// 注册TypeHandler Class --> TypeHandler 实例映射关系,如果JavaType不为空,注册JavaType --> Map 映射关系

private void register(Type javaType, JdbcType jdbcType, TypeHandler handler) {

   if (javaType != null) {

     Map> map = TYPE_HANDLER_MAP.get(javaType);

     if (map == null || map == NULL_TYPE_HANDLER_MAP) {

       map = new HashMap>();

  // 一个Java类型可能对应多个TypeHandler

       TYPE_HANDLER_MAP.put(javaType, map);

     }

     map.put(jdbcType, handler);

   }

   

   // TypeHandler Class --> TypeHandler 实例

   ALL_TYPE_HANDLERS_MAP.put(handler.getClass(), handler);

 }

 

2.7 扫描指定包注册TypeHandler

 public void register(String packageName) {

   // 扫描指定包下实现TypeHandler接口的类

   ResolverUtil> resolverUtil = new ResolverUtil>();

   resolverUtil.find(new ResolverUtil.IsA(TypeHandler.class), packageName);

   Set>> handlerSet = resolverUtil.getClasses();

   for (Class type : handlerSet) {

     // 忽略内部类和接口(包括package-info.java)和抽象类

     if (!type.isAnonymousClass() && !type.isInterface() && !Modifier.isAbstract(type.getModifiers())) {

  // 传送门:5.2

       register(type);

     }

   }

 }

你可能感兴趣的:(Mybatis3)