当前位置: 首页 > news >正文

【Mybatis源码分析】TypeAliasRegistry源码分析

TypeAliasRegistry源码分析

  • 一、引入类型别名
  • 二、typeAlias 的三种配置方式
  • 三、TypeAliasRegistry源码分析
    • 三种配置方式源码解析
    • 校验过程
    • Mybatis默认的别名配置
  • 四、总结

一、引入类型别名

当配置 XML 文件,需要指明Java类型时,类型别名可替代Java类型的全名,一般会设置一个简单缩写的类型别名去替代它,用于XML配置,以降低冗余的全限定类名书写。(说白了其作用就是偷懒)

下面是使用全限定类名指定的配置:

    <select id="selectAll" resultType="com.ncpowernode.mybatis.bean.User">select * from t_user;</select>

当在核心配置文件中配置完后:

在这里插入图片描述
即可写成下面的形式:

<select id="selectAll" resultType="user">select * from t_user;
</select>

二、typeAlias 的三种配置方式

  1. type属性和alias属性双搭
<typeAlias type="com.ncpowernode.mybatis.bean.User" alias="user"/>
  1. 直接写type属性指定全限定类名,底层会利用该类的simpleName去当作这个alias。
<typeAlias type="com.ncpowernode.mybatis.bean.User"/>
  1. 直接配置包标签,使得指定包下的所有类都进行别名配置。
<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);}}}

校验过程

通过阅读下面源码可以知道:

  1. 为什么使用别名的时候各个字符不区分大小写;
  2. 为什么使用别名也行,使用全限定类名也行。
  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对象封装起来的就完成了。解析核心配置文件扩大别名使用,有懒就偷。

相关文章:

【Mybatis源码分析】TypeAliasRegistry源码分析

TypeAliasRegistry源码分析一、引入类型别名二、typeAlias 的三种配置方式三、TypeAliasRegistry源码分析三种配置方式源码解析校验过程Mybatis默认的别名配置四、总结一、引入类型别名 当配置 XML 文件&#xff0c;需要指明Java类型时&#xff0c;类型别名可替代Java类型的全…...

节点高负载

如何判断节点高负载? 可以通过 top 或 uptime 来确定 load 大小,如果 load 小于 CPU 数量,属于低负载,如果大于 CPU 数量 2~3 倍,就比较高了,当然也看业务敏感程度,不太敏感的大于 4 倍算高负载。 排查思路 观察监控:通常不是因为内核 bug 导致的高负载,在卡死之前…...

动态规划(一) part1

T1:一个数组 中的最长 升序 子序列 的长度 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组…...

Ubuntu显卡报错:Failed to initialize NVML Driver/library version mismatch

问题描述 输入指令nvidia-smi的时候&#xff0c;出现如下&#xff1a; Failed to initialize NVML: Driver/library version mismatch看起来好像是版本不匹配&#xff0c;在网上查了很多都没有解决问题&#xff0c;重启也不行&#xff0c;结果证明最好的办法是重新安装cuda。…...

JAVA企业电子采购系统源码:采购过程更规范,更透明

满足采购业务全程数字化&#xff0c; 实现供应商管理、采购需求、全网寻源、全网比价、电子招 投标、合同订单执行的全过程管理。 电子招标采购&#xff0c;是指在网上寻源和采购产品和服务的过程。对于企业和企业主来说&#xff0c;这是个既省钱又能提高供应链效率的有效方法…...

5.5G产业再提速!高通5GAdvanced-ready芯片商用终端下半年面世

MWC2023大会召开在即&#xff0c;5GAdvanced产业再添重磅消息&#xff01;2月15日&#xff0c;高通宣布推出全球首个5GAdvanced-ready基带芯片——骁龙X755G调制解调器及射频系统&#xff0c;支持毫米波和Sub-6GHz频段&#xff0c;带来网络覆盖、时延、能效和移动性等全方位的提…...

基于B站王阿华的视频——为什么当下自媒体都在制造焦虑以及如何摆脱

观后笔记2.0——一些深入的思考 1.情绪大约在两千万年前&#xff0c;哺乳脑统治期间诞生。 2.情绪分为积极情绪和负面情绪。决定某种情绪的出现取决于安全感等级。 自媒体制造负面情绪&#xff0c;想尽办法挑起情绪&#xff0c;吸引流量 安全感充足时&#xff0c;由积极情绪…...

一、Docker介绍:

Docker官方网站&#xff1a;https://www.docker.com/ Docker容器技术是虚拟化技术的一个分支&#xff0c;虚拟化技术一般分为两种&#xff1a; 硬件级虚拟化&#xff08;hardware-level-virtualization&#xff09; &#xff1a;是运行在硬件之上的虚拟化技术&#xff0c;它的核…...

Vue进阶(一篇进入Vue3的世界)

文章目录一、初识Vue3二、Vue3新语法糖setup三、响应式数据函数3.1 ref函数3.2 reactive函数3.3 ref和reactive函数的异同四、Vue3的响应式原理五、语法更新5.1 Vue3使用computed计算属性5.2 Vue3使用watch监视属性的注意点5.2.1 监视ref对象5.2.2 监视reactive对象5.2.3 监视嵌…...

功能测试的分类,分别有什么作用?

目录 前言 一、链接测试 二、表单测试 三、搜索测试 四、删除测试 五、cookies/session测试 六、数据库测试 七、峰值测试/容量测试 八、相容性测试/安全测试 前言 功能测试主要包括链接测试、表单测试、搜索测试、删除测试、cookies、session测试、数据库测试等部分…...

51单片机学习笔记_14 红外遥控

红外传感器 遥控器通过红外 LED 发送调制后的信号&#xff0c;开发板上的红外接收模块接收遥控器的红外线。 单工异步&#xff0c;940nm 波长&#xff08;还有一种 250nm 的N&#xff0c;可见光&#xff09;&#xff0c;EC 通信标准。 38KHz&#xff1a;红外线频率。 IN&…...

【我是土堆 - Pytorch教程】 知识点 学习总结笔记(五)

此文章为【我是土堆 - Pytorch教程】 知识点 学习总结笔记&#xff08;五&#xff09;包括&#xff1a;完整的模型训练套路&#xff08;一&#xff09;、完整的模型训练套路&#xff08;二&#xff09;、完整的模型训练套路&#xff08;三&#xff09;、利用GPU训练&#xff08…...

JUC篇:CopyOnWriteArrayList的应用与原理

系列文章目录 JUC篇&#xff1a;volatile可见性的实现原理 JUC篇&#xff1a;synchronized的应用和实现原理 JUC篇&#xff1a;用Java实现一个简单的线程池 JUC篇&#xff1a;java中的线程池 JUC篇&#xff1a;ThreadLocal的应用与原理 JUC篇&#xff1a;Java中的并发工具类 文…...

【总结】爬虫1-requests

爬虫1-requests 1. requests的基本用法 requests需要提前导入&#xff0c;才能使用 1.1 请求网络数据&#xff1a;requests.get(请求地址) response requests.get(https://cd.zu.ke.com/zufang)1.2 设置解码方法&#xff08;罗马的是需要设置 - 一定要在获取请求结果之前设…...

基于springboot实现学生综合成绩测评系统【源码】分享

基于springboot实现学生综合成绩测评系统演示开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包…...

uniapp初体验———uView组件库的使用与钉钉小程序的运行

这周学长给了我一个校企合作的项目&#xff0c;要求是用uniapp开发&#xff0c;最终打包成钉钉小程序&#xff0c;不过我并不会uniapp&#xff0c;也是学了一段时间&#xff0c;开始写项目&#xff0c;中间也遇到过很多问题&#xff0c;比如开发者工具还有如何运行到开发者工具…...

初始Go语言2【标识符与关键字,操作符与表达式,变量、常量、字面量,变量作用域,注释与godoc】

文章目录Go语言基础语法标识符与关键字操作符与表达式变量、常量、字面量变量类型变量声明变量初始化常量字面量变量作用域注释与godoc注释的形式注释的位置go docgodocGo语言基础语法 标识符与关键字 go变量、常量、自定义类型、包、函数的命名方式必须遵循以下规则&#xff…...

Vue计算属性详解

目录 ​编辑 1、什么是计算属性 2、为什么要有计算属性 1. 为什么不是使用模板语法 2. 为什么不是使用method对于复杂逻辑 3. 什么时候要用计算属性 4. 定义计算属性fullName 5. 计算属性的配置项 1、什么是计算属性 写在computed对象中的属性&#xff0c;本质上是…...

rk3568-AD按键驱动调试

rk3568-AD按键驱动调试转载请备注&#xff1a;daisy.skye的博客_CSDN博客-Qt,嵌入式,Linux领域博主dts设备树节点 /rk356x_linux_220118/kernel/arch/arm64/boot/dts/rockchip/rk3568.dtsi 板级设备树dts /home/scooper/jkD7/20221221/ido_evb3568_v2_android11_sdk/kernel/…...

Docker三剑客之swarm

一、什么是docker swarm Swarm是Docker公司推出的用来管理docker集群的平台&#xff0c;几乎全部用GO语言来完成的开发的&#xff0c;代码开源在https://github.com/docker/swarm&#xff0c; 它是将一群Docker宿主机变成一个单一的虚拟主机&#xff0c;Swarm使用标准的Docker…...

Lucene Solr Elasticsearch三者之间的关系,怎么选?

Lucene简介&#xff1a; Lucene主要用于构建文本搜索应用程序&#xff0c;包括Web搜索引擎、桌面搜索工具和商业应用程序。它提供了诸如单词分析、查询解析、搜索结果排序等功能&#xff0c;可以轻松地在大量文档中快速搜索和查找相关信息。 Lucene具有以下特点&#xff1a; …...

为你的网站加上Loading等待加载效果吧 | Loading页面加载添加教程

为你的网站加上Loading等待加载效果吧 | Loading页面加载添加教程 效果图 : 教程开始 新建一个loading样式css 将以下代码放进去 然后引用这个文件 code #Loadanimation{ background-color:#fff; height:100%; width:100%; position:fixed; z-index:1; ma…...

Redis安装和配置

网上有海量的Redis文章&#xff0c;写的都很详细。这里就是简单记录一下自己查aof问题过程中遇到的问题&#xff0c;主要是aof文件所在目录在redis.conf里的位置 1。在ubuntu16上安装Redis sudo apt-get install -y redis-server 2。修改redis配置 sudo vim /etc/redis/re…...

MobTech|如何使用秒验

什么是秒验&#xff1f; 秒验是MobTech公司提供的一款实现一键验证功能的产品&#xff0c;从根源上降低企业验证成本&#xff0c;有效提高拉新转化率&#xff0c;降低因验证带来的流失率&#xff0c;3秒完成手机号验证&#xff08;一键登录&#xff09;。 秒验主要整合了三大…...

CSS实现自动分页打印同时每页保留重复的自定义内容

当需要打印的内容过长时系统会产生自动分割页面&#xff0c;造成样式不太美观。使用CSS的 media print 结合 <table> 可以实现对分页样式的可控。效果如下&#xff1a; 假设有50条数据&#xff0c;打印时系统会自动分成两页&#xff0c;同时每页保留自定义的header和foo…...

基于prometheus的监控告警怎么实现?

基于 Prometheus 的监控告警实现一般需要以下几个步骤&#xff1a; 安装和配置 Prometheus&#xff1a;安装 Prometheus 并配置好需要监控的目标。可以使用 Prometheus 的配置文件&#xff08;prometheus.yml&#xff09;来指定需要监控的目标&#xff0c;例如服务、主机、容器…...

2007年4月全国计算机等级考试二级JAVA笔试试题及答案

2007年4月全国计算机等级考试二级JAVA笔试试题及答案 一、选择题 &#xff08;1&#xff09;已知一棵二叉树前序遍历和中序遍历分别为ABDEGCFH和DBGEACHF&#xff0c;则该二叉树的后序遍历为 A&#xff0e;GEDHFBCA B&#xff0e;DGEBHFCA C&#xff0e;ABCDEFGH D&#xff0e;…...

灌水玩玩 ChatGPT AIGC生成的有栈协同程序实现(例子)

CO&#xff1a; 你是一名 C/C 高级软件工程师。 请使用 stackful 协程&#xff0c;实现一个 Sleep 随眠的协同程序&#xff0c;注意并非 stackless 协程&#xff0c;不允许使用 C/C 17 以上的语言标准实现&#xff0c;允许使用 boost 基础框架类库。 ChatGPT&#xff1a; 好的…...

【砝码称重】暴力DFS(一半分)+ dp(可AC)

题目描述&#xff1a; 题目分析&#xff1a; 我也没有完全搞太明白&#xff0c;简单说说我的理解 1.dp【i】【j】表示前 i 个砝码&#xff0c;是否可以称出来重量为 j 的物品&#xff0c;如果可以的话&#xff0c;值为1&#xff0c;不可以 为0&#xff1b; 2.针对当前第 i 个…...

科大奥瑞物理实验——霍尔效应实验

实验名称&#xff1a;霍尔效应实验 1. 实验目的&#xff1a; 了解霍尔效应测量磁场的原理和方法&#xff1b;观察磁电效应现象&#xff1b;学会用霍尔元件测量磁场及元件参数的基本方法。 2. 实验器材&#xff1a; QS-H型霍尔效应实验仪 磁针 QS-H型霍尔效应测试仪 双刀开关…...