源码追踪,记typeAliasesPackage的使用(ruoyi-cloud中一个疑问的启发)

2023-10-27

首先,提一个思考题:在mapper.xml文件中写sql的时候,parameterType指明入参类型的时候,为什么只需要写String,Long,Integer等,而不用写java.lang.String,java.lang.Long这样呢?

其实是因为springboot在启动并自动初始化bean的过程中,会去加载一个叫TypeAliasRegistry的类,该类的构造器初始化了常用的所有数据类型如下:

private final Map<String, Class<?>> typeAliases = new HashMap();
public TypeAliasRegistry() {
        this.registerAlias("string", String.class);
        this.registerAlias("byte", Byte.class);
        this.registerAlias("long", Long.class);
        this.registerAlias("short", Short.class);
        this.registerAlias("int", Integer.class);
        this.registerAlias("integer", Integer.class);
        this.registerAlias("double", Double.class);
        this.registerAlias("float", Float.class);
        this.registerAlias("boolean", Boolean.class);
        this.registerAlias("byte[]", Byte[].class);
        this.registerAlias("long[]", Long[].class);
        this.registerAlias("short[]", Short[].class);
        this.registerAlias("int[]", Integer[].class);
        this.registerAlias("integer[]", Integer[].class);
        this.registerAlias("double[]", Double[].class);
        this.registerAlias("float[]", Float[].class);
        this.registerAlias("boolean[]", Boolean[].class);
        this.registerAlias("_byte", Byte.TYPE);
        this.registerAlias("_long", Long.TYPE);
        this.registerAlias("_short", Short.TYPE);
        this.registerAlias("_int", Integer.TYPE);
        this.registerAlias("_integer", Integer.TYPE);
        this.registerAlias("_double", Double.TYPE);
        this.registerAlias("_float", Float.TYPE);
        this.registerAlias("_boolean", Boolean.TYPE);
        this.registerAlias("_byte[]", byte[].class);
        this.registerAlias("_long[]", long[].class);
        this.registerAlias("_short[]", short[].class);
        this.registerAlias("_int[]", int[].class);
        this.registerAlias("_integer[]", int[].class);
        this.registerAlias("_double[]", double[].class);
        this.registerAlias("_float[]", float[].class);
        this.registerAlias("_boolean[]", boolean[].class);
        this.registerAlias("date", Date.class);
        this.registerAlias("decimal", BigDecimal.class);
        this.registerAlias("bigdecimal", BigDecimal.class);
        this.registerAlias("biginteger", BigInteger.class);
        this.registerAlias("object", Object.class);
        this.registerAlias("date[]", Date[].class);
        this.registerAlias("decimal[]", BigDecimal[].class);
        this.registerAlias("bigdecimal[]", BigDecimal[].class);
        this.registerAlias("biginteger[]", BigInteger[].class);
        this.registerAlias("object[]", Object[].class);
        this.registerAlias("map", Map.class);
        this.registerAlias("hashmap", HashMap.class);
        this.registerAlias("list", List.class);
        this.registerAlias("arraylist", ArrayList.class);
        this.registerAlias("collection", Collection.class);
        this.registerAlias("iterator", Iterator.class);
        this.registerAlias("ResultSet", ResultSet.class);
    }
public void registerAlias(String alias, Class<?> value) {
        if (alias == null) {
            throw new TypeException("The parameter alias cannot be null");
        } else {
            String key = alias.toLowerCase(Locale.ENGLISH);
            if (this.typeAliases.containsKey(key) && this.typeAliases.get(key) != null && !((Class)this.typeAliases.get(key)).equals(value)) {
                throw new TypeException("The alias '" + alias + "' is already mapped to the value '" + ((Class)this.typeAliases.get(key)).getName() + "'.");
            } else {
                this.typeAliases.put(key, value);
            }
        }
    }

DEBUG启动过程中打上断点,效果如下,可以推测,当该类初始化完成之后,会将构造器中传入的所有数据类型装载到这个叫typeAliases的Map中。

 然后初始化sqlSessionFactory的过程中,会调用resolveAlias方法解析,代码如下

public <T> Class<T> resolveAlias(String string) {
        try {
            if (string == null) {
                return null;
            } else {
                String key = string.toLowerCase(Locale.ENGLISH);
                Class value;
                if (this.typeAliases.containsKey(key)) {
                    value = (Class)this.typeAliases.get(key);
                } else {
                    value = Resources.classForName(string);
                }

                return value;
            }
        } catch (ClassNotFoundException var4) {
            throw new TypeException("Could not resolve type alias '" + string + "'.  Cause: " + var4, var4);
        }
    }

DEBUG运行如下:

可以看到,我们在xml文件中写的string,在这里会先进if判断在typeAliases中是否有string,有就会进入下面的代码

value = (Class)this.typeAliases.get(key);

直接从里面取出string对应的全限定名java.lang.String。根据代码看,如果我们在xml中写全限定名java.lang.String,也是可以的,此时会进入else分支,通过反射获取到类。

到这里,前面的思考题就可以破案了。

为什么会去追这样一个属性的源码呢?源于开源项目ruoyi-cloud的system模块中的一个写法,在nacos配置中心可以看到,该模块采用了typeAliasesPackage为所有类指定了别名

 这里只写到了system,而实际上该模块的实体类都在com.ruoyi.system.domain下面,这个属性会扫描该目录以及其子目录,所以这样写是可以解析到的,没有问题。但是当我把domain加上去的时候,按道理说也应该不会有问题啊,然而启动的时候直接报错了,报一个找不到SysDept类的异常,于是debug了一下,效果如下:

可以看出,该类并不是 com.ruoyi.system.domain下面的,而是com.ruoyi.system.api.domain下面的,那么报错就是理所当然了。

找出错误后,就想着去跟一下这个别名的解析办法,于是有了这篇文章。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

源码追踪,记typeAliasesPackage的使用(ruoyi-cloud中一个疑问的启发) 的相关文章

  • 在 java 类和 android 活动之间传输时音频不清晰

    我有一个android活动 它连接到一个java类并以套接字的形式向它发送数据包 该类接收声音数据包并将它们扔到 PC 扬声器 该代码运行良好 但在 PC 扬声器中播放声音时会出现持续的抖动 中断 安卓活动 public class Sen
  • 如何找到给定字符串的最长重复子串

    我是java新手 我被分配寻找字符串的最长子字符串 我在网上研究 似乎解决这个问题的好方法是实现后缀树 请告诉我如何做到这一点或者您是否有任何其他解决方案 请记住 这应该是在 Java 知识水平较低的情况下完成的 提前致谢 附 测试仪字符串
  • 在 HTTPResponse Android 中跟踪重定向

    我需要遵循 HTTPost 给我的重定向 当我发出 HTTP post 并尝试读取响应时 我得到重定向页面 html 我怎样才能解决这个问题 代码 public void parseDoc final HttpParams params n
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 操作错误不会显示在 JSP 上

    我尝试在 Action 类中添加操作错误并将其打印在 JSP 页面上 当发生异常时 它将进入 catch 块并在控制台中打印 插入异常时出错 请联系管理员 在 catch 块中 我添加了它addActionError 我尝试在jsp页面中打
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • 如何将 pfx 文件转换为 jks,然后通过使用 wsdl 生成的类来使用它来签署传出的肥皂请求

    我正在寻找一个代码示例 该示例演示如何使用 PFX 证书通过 SSL 访问安全 Web 服务 我有证书及其密码 我首先使用下面提到的命令创建一个 KeyStore 实例 keytool importkeystore destkeystore
  • 使用Caliper时如何指定命令行?

    我发现 Google 的微型基准测试项目 Caliper 非常有趣 但文档仍然 除了一些示例 完全不存在 我有两种不同的情况 需要影响 JVM Caliper 启动的命令行 我需要设置一些固定 最好在几个固定值之间交替 D 参数 我需要指定
  • 总是使用 Final?

    我读过 将某些东西做成最终的 然后在循环中使用它会带来更好的性能 但这对一切都有好处吗 我有很多地方没有循环 但我将 Final 添加到局部变量中 它会使速度变慢还是仍然很好 还有一些地方我有一个全局变量final 例如android Pa
  • 如何在 javadoc 中使用“<”和“>”而不进行格式化?

    如果我写
  • AWS 无法从 START_OBJECT 中反序列化 java.lang.String 实例

    我创建了一个 Lambda 函数 我想在 API 网关的帮助下通过 URL 访问它 我已经把一切都设置好了 我还创建了一个application jsonAPI Gateway 中的正文映射模板如下所示 input input params
  • 无法捆绑适用于 Mac 的 Java 应用程序 1.8

    我正在尝试将我的 Java 应用程序导出到 Mac 该应用程序基于编译器合规级别 1 7 我尝试了不同的方法来捆绑应用程序 1 日食 我可以用来在 Eclipse 上导出的最新 JVM 版本是 1 6 2 马文 看来Maven上也存在同样的
  • 在mockito中使用when进行模拟ContextLoader.getCurrentWebApplicationContext()调用。我该怎么做?

    我试图在使用 mockito 时模拟 ContextLoader getCurrentWebApplicationContext 调用 但它无法模拟 here is my source code Mock org springframewo
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • 当我从 Netbeans 创建 Derby 数据库时,它存储在哪里?

    当我从 netbeans 创建 Derby 数据库时 它存储在哪里 如何将它与项目的其余部分合并到一个文件夹中 右键单击Databases gt JavaDB in the Service查看并选择Properties This will
  • 如何修复 JNLP 应用程序中的“缺少代码库、权限和应用程序名称清单属性”?

    随着最近的 Java 更新 许多人都遇到了缺少 Java Web Start 应用程序的问题Codebase Permissions and Application name体现属性 尽管有资源可以帮助您完成此任务 但我找不到任何资源综合的
  • 按日期对 RecyclerView 进行排序

    我正在尝试按日期对 RecyclerView 进行排序 但我尝试了太多的事情 我不知道现在该尝试什么 问题就出在这条线上适配器 notifyDataSetChanged 因为如果我不放 不会显示错误 但也不会更新 recyclerview
  • Spring Boot @ConfigurationProperties 不从环境中检索属性

    我正在使用 Spring Boot 1 2 1 并尝试创建一个 ConfigurationProperties带有验证的bean 如下所示 package com sampleapp import java net URL import j

随机推荐

  • 利用element的tree实现多级类目管理

    需求展示 UE图就如上所示 主要要实现的功能的就是在展示所有的类目同时可以增加 删除 编辑一级类目并且能在一级类目下增加 删除 编辑二级类目 实现思路 1 利用elementUI中的tree组件 传入数据 展示出初步效果 2 增加一级类目和
  • 流体力学示例 Python 分析(更新 3-11-2023)

    应用案例 Python 流体动力学层流建模 Python 创建有限体积流体模拟 伯努利方程示例 Python 计算 汽水流体和喷泉工程 聚焦流体力学基础及Python计算 提供了全面的主题覆盖 包含各种示例和问题 流体力学视觉组件的应用 包
  • 解决IDEA控制台中文乱码问题(Tomcat、动态网页项目)

    博主在使用idea的创建动态网页的时候 遇到了控制台中文乱码问题 在网上参考了多种解决方案之后 终于将问题成功解决 现在将自己遇到问题的情况和解决问题的方法总结如下 Idea控制台中文乱码问题通常有以下两种情况 博主是两种情况都发生了 一种
  • 认识 Kotlin 语言

    Kotlin 的背景 Kotlin 是一门基于 JVM 且与 JAVA 可 100 互通的编程语言 用 JetBrains 的话来说 Kotlin 是更 现代化 更强大 的编程语言 Kotlin 由 JetBrains 在 2010 年开发
  • 如何使用Pytest进行自动化测试(干货)

    为什么需要自动化测试 自动化测试有很多优点 但这里有3个主要的点 可重用性 不需要总是编写新的脚本 除非必要 即使是新的操作系统版本也不需要编写脚本 可靠性 人容易出错 机器不太可能 当运行不能跳过的重复步骤 测试时 速度会更快 全天运行
  • Windows ~~~ ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: NO)

    安装MySQL5或8出问题 1 ERROR 1045 28000 Access denied for user root localhost using password NO 1 1 解决方法 2 ERROR 1045 28000 Acc
  • 预测房价(Python)

    构建神经网络 深度学习模型的基本步骤 深度学习模型具有一定的通用性 使得深度学习的门槛降低 这是深度学习得以重新占据计算机领域一席之地的重要原因 深度学习均可以从下述五个步骤来完成模型的构建和训练 def load data 从文件导入数据
  • 攻防世界新手区web simple_php

    simple php 不认识show source函数 百度一下 可知这个函数是对测试文件 test php 进行 PHP 语法高亮显示 可大致理解为提交a和b的正确形式可得到flag 百度可知is numeric函数判断是否为数字或数字字
  • 与众不同的协同办公工具——飞书

    其实很早就知道飞书 但真正深入了解 还是最近一个月的事情 因为一个知识付费产品的强烈推荐 我才真正试用了一下 试完之后 很有启发 觉得有必要整理和总结一下 以便后续继续深入使用 飞书有什么不同 我觉得有如下三点 第一 不一样的沟通方式 它力
  • windows使用命令行创建文件echo >test.txt(可以是.gp .js .ts..)

    或多说直接上代码 第一步 打开命令行 进入要创建的目录 C Users gt cd C Users lenovo Desktop node 第二步 输入创建文件的指令 echo gt 文件名字 文件名字 就是常见的文件 例如 txt js
  • 关于echarts中南海诸岛的显示问题

    关于echarts中南海诸岛的显示问题 1 china js 文件中 echarts registerMap china 名字要是 china 不能写成 中国 2 echarts 配置中地图名称 mapName china var myCh
  • sequence中实现寄存器前门访问的4种方法

    uvm sequence中实现寄存器访问的方法 在芯片的eda仿真过程中 有的场景需要在发包控制的时候对dut的寄存器进行一些动态配置 这就需要通过寄存器模型来对相关寄存器进行读写操作 小结三种方法如下 通过uvm top这个全局变量来获取
  • django系列 第一节

    一 安装python 安装django 使用虚拟环境 Virtualenv python3的安装方法 http blog csdn net xudailong blog article details 78309857 django的安装方
  • LeetCode(力扣) 312题:戳气球----动态规划求解附带详细注释

    问题描述 有n个气球 编号为 0 到 n 1 每个气球上都标有一个数字 这些数字存在于数组nums中 现在要求你戳破所有的气球 戳破第 i 个气球 你可以获得nums i 1 nums i nums i 1 枚硬币 这里的 i 1 和 i
  • linux给用户添加文件夹的使用权限

    添加权限 将目录 opt 及其下面的所有文件 子目录的文件主改成 liuhai chown R liuhai liuhai opt root localhost sudo chown R oracle home 选项 c或 changes
  • postgresql 服务无法启动,日志中报如下错误

    1 postgresql 服务无法启动 日志中报如下错误 磁盘空间足够 无法找到来自源 PostgreSQL 的事件 ID 0 的描述 本地计算机上未安装引发此事件的组件 或者安装已损坏 可以安装或修复本地计算机上的组件 1 使用pg co
  • 因特网中的电子邮件--应用层协议

    因特网中的电子邮件 因特网中的电子邮件系统主要由三部分组成 用户代理 user agent 邮件服务器 mail server 简单邮件传输协议 Simple Mail Transfer Protocol SMTP 邮件服务器为电子邮件系统
  • matlab计算数据MEA与RMSE误差指标

    MEA Mean Absolute Error 均方差 和RMSE Root Mean Square Error 均方根误差 是两个经常使用的误差评价指标 用于评价模型预测值与真实值之间的误差大如其间的误差 1 MEA 均方差 将预测结果与
  • fastadmin列表自动刷新功能

    在fastadmin框架中 将列表自动刷新给屏蔽了 如果要开启的话 有点麻烦 需要去重新修改框架核心的js代码 然后还需要重新进行编译 在看开发文档的时候 发现列表是存在refresh的方法 既然有这个方法在 那么是否能结合JS的定时器来做
  • 源码追踪,记typeAliasesPackage的使用(ruoyi-cloud中一个疑问的启发)

    首先 提一个思考题 在mapper xml文件中写sql的时候 parameterType指明入参类型的时候 为什么只需要写String Long Integer等 而不用写java lang String java lang Long这样