Mybatis中TypeAliasRegistry的作用及使用方法
作者:假正经的小柴 发布时间:2023-06-27 19:21:32
一、引入类型别名
当配置 XML 文件,需要指明Java类型时,类型别名可替代Java类型的全名,一般会设置一个简单缩写的类型别名去替代它,用于XML配置,以降低冗余的全限定类名书写。(说白了其作用就是偷懒)
下面是使用全限定类名指定的配置:
<select id="selectAll" resultType="com.ncpowernode.mybatis.bean.User">
select * from t_user;
</select>
当在核心配置文件中配置完后:
<typeAliases>
<! --<package name="com.ncpowernode .mybatis.bean" />-->
<typeAlias type="com.ncpowernode .mybatis.bean. User"/>
</typeAliases>
即可写成下面的形式:
<select id="selectAll" resultType="user">
select * from t_user;
</select>
二、typeAlias的三种配置方式
type属性和alias属性双搭
<typeAlias type="com.ncpowernode.mybatis.bean.User" alias="user"/>
直接写type属性指定全限定类名,底层会利用该类的simpleName
去当作这个alias。
<typeAlias type="com.ncpowernode.mybatis.bean.User"/>
直接配置包标签,使得指定包下的所有类都进行别名配置。
<package name="com.ncpowernode.mybatis.bean"/>
三、TypeAliasRegistry源码分析
三种配置方式源码解析
Mybatis通过TypeAliasRegistry
对象实现对别名的封装,实现别名对应Java类型的校验。TypeAliasRegistry类中是用一Map成员对象实现上面封装效果的。
public class TypeAliasRegistry {
// key对应着别名,Class对应着全限定类名转换的Class对象
private final Map<String, Class<?>> typeAliases = new HashMap<>();
}
解析核心配置文件时候支持上面提到的三种设置别名的方式,那自然底层实现也存在三种,但万变不理其中,最后跳转到的代码(核心方法)如下所示:
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);
// 从这段代码可以知道别名可以支持多个对应一个Class对象
if (typeAliases.containsKey(key) && typeAliases.get(key) != null && !typeAliases.get(key).equals(value)) {
throw new TypeException(
"The alias '" + alias + "' is already mapped to the value '" + typeAliases.get(key).getName() + "'.");
}
// 封装到Map中
typeAliases.put(key, value);
}
下面对三种方式源码进行解析
第一种:type和alias属性双用(直接跳转到上面核心方法)
public void registerAlias(String alias, String value) {
registerAlias(alias, Resources.classForName(value));
}
第二种:仅用type属性(熟知的简单类名,为什么是简单类名当作别名下面的代码很好的体现出来了,还有一种设置别名的方式是使用@Alias注解,但小编本人不喜欢用)
public void registerAlias(Class<?> type) {
// 获取类中的简单类名称,充当别名
String alias = type.getSimpleName();
// 如果在对应类上用了@Alias注解的话,那对应的是@Alias注解中的value属性值
// 但小编不建议用,出错了感觉不好排查
Alias aliasAnnotation = type.getAnnotation(Alias.class);
if (aliasAnnotation != null) {
alias = aliasAnnotation.value();
}
// 进行封装
registerAlias(alias, type);
}
第三种:使用package标签(常用)
public void registerAliases(String packageName) {
registerAliases(packageName, Object.class);
}
public void registerAliases(String packageName, Class<?> superType) {
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
// 获取包下的类Class对象,仅该目录下的,子目录下的类对象不包括
resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();
for (Class<?> type : typeSet) {
// 对应的类不能是匿名类/接口
if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
// 本质是使用第二种方式
registerAlias(type);
}
}
}
校验过程
通过阅读下面源码可以知道:
为什么使用别名的时候各个字符不区分大小写;
为什么使用别名也行,使用全限定类名也行。
public <T> Class<T> resolveAlias(String string) {
try {
// 判断传来的别名(也可能是全限定类名)不为空
if (string == null) {
return null;
}
// 解析的时候都会转换成小写
// 这就是为什么使用别名的时候别名字母小写大写无所谓
String key = string.toLowerCase(Locale.ENGLISH);
Class<T> value;
if (typeAliases.containsKey(key)) {// 通过别名查找对应的value(Class对象)
value = (Class<T>) typeAliases.get(key);
} else {// 无别名就当作全限定类名处理,不存在就会抛出下面的异常
value = (Class<T>) Resources.classForName(string);
}
// 返回结果Class对象
return value;
} catch (ClassNotFoundException e) {
throw new TypeException("Could not resolve type alias '" + string + "'. Cause: " + e, e);
}
}
Mybatis默认的别名配置
Mybatis 在初始化Configuration对象的时候自身配置了一些Java类型的类型别名。如下所示:
这是Configuration类中TypeAliasRegistry成员初始化创建对象时候进行的配置
// TypeAliasRegistry类构造器初始化
public TypeAliasRegistry() {
registerAlias("string", String.class);
registerAlias("byte", Byte.class);
registerAlias("char", Character.class);
registerAlias("character", Character.class);
registerAlias("long", Long.class);
registerAlias("short", Short.class);
registerAlias("int", Integer.class);
registerAlias("integer", Integer.class);
registerAlias("double", Double.class);
registerAlias("float", Float.class);
registerAlias("boolean", Boolean.class);
registerAlias("byte[]", Byte[].class);
registerAlias("char[]", Character[].class);
registerAlias("character[]", Character[].class);
registerAlias("long[]", Long[].class);
registerAlias("short[]", Short[].class);
registerAlias("int[]", Integer[].class);
registerAlias("integer[]", Integer[].class);
registerAlias("double[]", Double[].class);
registerAlias("float[]", Float[].class);
registerAlias("boolean[]", Boolean[].class);
registerAlias("_byte", byte.class);
registerAlias("_char", char.class);
registerAlias("_character", char.class);
registerAlias("_long", long.class);
registerAlias("_short", short.class);
registerAlias("_int", int.class);
registerAlias("_integer", int.class);
registerAlias("_double", double.class);
registerAlias("_float", float.class);
registerAlias("_boolean", boolean.class);
registerAlias("_byte[]", byte[].class);
registerAlias("_char[]", char[].class);
registerAlias("_character[]", char[].class);
registerAlias("_long[]", long[].class);
registerAlias("_short[]", short[].class);
registerAlias("_int[]", int[].class);
registerAlias("_integer[]", int[].class);
registerAlias("_double[]", double[].class);
registerAlias("_float[]", float[].class);
registerAlias("_boolean[]", boolean[].class);
registerAlias("date", Date.class);
registerAlias("decimal", BigDecimal.class);
registerAlias("bigdecimal", BigDecimal.class);
registerAlias("biginteger", BigInteger.class);
registerAlias("object", Object.class);
registerAlias("date[]", Date[].class);
registerAlias("decimal[]", BigDecimal[].class);
registerAlias("bigdecimal[]", BigDecimal[].class);
registerAlias("biginteger[]", BigInteger[].class);
registerAlias("object[]", Object[].class);
registerAlias("map", Map.class);
registerAlias("hashmap", HashMap.class);
registerAlias("list", List.class);
registerAlias("arraylist", ArrayList.class);
registerAlias("collection", Collection.class);
registerAlias("iterator", Iterator.class);
registerAlias("ResultSet", ResultSet.class);
}
这是Configuration对象创建时候的别名配置
public Configuration() {
typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
typeAliasRegistry.registerAlias("LRU", LruCache.class);
typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);
typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
}
这些都是Mybatis框架会配置好的,你可以直接使用。
四、总结
TypeAliasRegistry 类完成的别名机制,总的来说源码还是比较简单的,一个Map对象封装起来的就完成了。解析核心配置文件扩大别名使用,有懒就偷。
来源:https://blog.csdn.net/qq_63691275/article/details/129813264


猜你喜欢
- 概述Spring针对Java Transaction API (JTA)、JDBC、Hibernate和Java Persistence A
- 使用WebClient和htmlunit实现简易爬虫import com.gargoylesoftware.htmlunit.WebClie
- 前言需求是上传Excel文件并读取Excel文件中的内容,根据获取的数据执行完某些业务操作后再将一些数据写回到excel中。前台使用Form
- tcp一般用于维持一个可信任的连接,比起udp更为安全可靠,在vs.net,分别有tcpclient和udpclient以及tcpliste
- 题目:打印出所有的 "水仙花数 ",所谓 "水仙花数 "是指一个三位数,其各位数字立方和等于该数本身
- 微信小程序 跳转页面小程序页面有2种跳转,可以在wxml页面或者js中:1,在wxml页面中: <navigator url=&quo
- 一、添加依赖<!--SpringBoot使用Swagger2构建API文档的依赖--> <dep
- 一、可变参数方法的定义首先看下可变参数方法在代码上是如何定义的,如下所示:public static void method1(Intege
- 分部类(Partial Class)在C#2.0引入,分部方法(Partial Method)在C#3.0引入,这两个语法特性都具有相同的特
- 这篇文章主要介绍了Java CPU性能分析工具代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋
- 重新启动IDEA maven项目SSM框架所有@注解失效,每个文件上都有个小黄圆,而且我发现所有构建项目的maven的jar包都不在了,也就
- 创建maven父子工程时遇到一个问题,当子工程的名称前缀和父工程的名称一样时,子工程会出现一系列的问题。比如我的父工程名称是microser
- 想必我们在做项目的时候,都会遇到服务端与客户端交互数据。一般情况下我们都会采用json格式或者xml格式,将服务端的数据转换成这两种格式之一
- 1.项目介绍本项目旨在打造一个基于RBAC架构模式的通用的、并不复杂但易用的权限管理系统。通过本项目可以较好的理解权限系统的常见业务同时学习
- 1. web.xml中配置了CharacterEncodingFilter,配置这个是拦截所有的资源并设置好编号格式。encoding设置成
- 参考链接亲测试以下版本成功激活附激活教程。idea下载链接(对应版本号下载):https://www.jetbrains.com/idea/
- Android Studio连接手机设备教程,供大家参考,具体内容如下一、ADB环境配置1.查看自己Android Studio配置的sdk
- 前言static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量
- 本文实例为大家分享了Android实现竖直跑马灯效果的具体代码,供大家参考,具体内容如下首先给出跑马灯效果图中间的色块是因为视频转成GIF造
- 如下图:点击加号添加键值对:archetypeCataloginternal补充知识:idea+maven+tomcat报404我的解决办法