Mybatis源码之(TypeAliasRegistry)TypeAlias别名实现机制

原文链接:http://blog.csdn.net/qq924862077/article/details/52612589

----------------------------------

在Mybatis编程中我们经常会用到将某个bean作为参数类型parameterType或者结果返回值类型ResultType,所以很多时候我们需要把完成的Bean的包名在mapper文件中写上,如下:

[html] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. <select id="selectUser" parameterType="com.dy.entity.User" resultType="com.dy.entity.User">    
  2.     select * from user where c_id=#{id}    
  3. </select>    

Mybatis给我们提供了一种叫别名的机制,意思就是对某个具体的类设置别名,在mybatis的配置文件中配置如下:

[html] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. <configuration>  
  2.     <typeAliases>  
  3.       <!--  
  4.       通过package, 可以直接指定package的名字, mybatis会自动扫描你指定包下面的javabean,  
  5.       并且默认设置一个别名,默认的名字为: javabean 的首字母小写的非限定类名来作为它的别名。  
  6.       也可在javabean 加上注解@Alias 来自定义别名, 例如: @Alias(user)   
  7.       <package name="com.dy.entity"/>  
  8.        --> 

  9.       <typeAlias alias="user" type="com.dy.entity.User"/>  

  10.   </typeAliases>  
  11.     
  12.   ......  
  13.     
  14. </configuration>  

这样之后mapper文件中的select可以写成如下格式:

[html] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. <select id="selectUser" parameterType="user" resultType="user">    
  2.     select * from user where c_id=#{id}    
  3. </select>    

这样就可以在使用某个bean时使用别名就可以了,不需要写完成的包名+类名

接下来我们介绍TypeAlias别名的实现机制

(1)我们在mybatis的配置文件中配置了typeAliases,我们首先分析XMLConfigBuilder类中对于typeAliases的解析,源码如下:

[java] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. //类别名解析  
  2.   private void typeAliasesElement(XNode parent) {  
  3.     if (parent != null) {  
  4.       for (XNode child : parent.getChildren()) {  
  5.         //如果子节点是package,那么就获取package节点的name属性  
  6.         if ("package".equals(child.getName())) {  
  7.           String typeAliasPackage = child.getStringAttribute("name");  
  8.           configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);  
  9.         } else {  
  10.         //如果子节点是typeAlias节点,那么就获取alias属性和type的属性  
  11.           String alias = child.getStringAttribute("alias");  
  12.           String type = child.getStringAttribute("type");  
  13.           try {  
  14.             //通过type的值来加载获得类  
  15.             Class<?> clazz = Resources.classForName(type);  
  16.             if (alias == null) {  
  17.             //typeAliasRegistry会进行别名注册  
  18.               typeAliasRegistry.registerAlias(clazz);  
  19.             } else {  
  20.               typeAliasRegistry.registerAlias(alias, clazz);  
  21.             }  
  22.           } catch (ClassNotFoundException e) {  
  23.             throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e);  
  24.           }  
  25.         }  
  26.       }  
  27.     }  

通过分析源码我们可以得知,解析alias来获得别名,解析type元素来获得类名,通过Resources.classForName(type)获得类信息,然后通过typeAliasRegistry.registerAlias(alias, clazz)将类别名注册到typeAliasRegistry中,这样就完成了mybatis中配置文件的解析。

(3)TypeAliasRegistry:是用来记录别名alias和类clazz之间的对应关系的,它可以看做是一个Map,alias作为key,类名作为value,详看源码如下:

[java] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. //其实就是一个map结构,用来对象key别名和value具体的类  
  2. public class TypeAliasRegistry {  
  3.   
  4.   private final Map<String, Class<?>> TYPE_ALIASES = new HashMap<String, Class<?>>();  
  5.   
  6.   public TypeAliasRegistry() {  
  7.     registerAlias("string", String.class);  
  8.   
  9.     registerAlias("byte", Byte.class);  
  10.     registerAlias("long", Long.class);  
  11.     registerAlias("short", Short.class);  
  12.     registerAlias("int", Integer.class);  
  13.     registerAlias("integer", Integer.class);  
  14.     registerAlias("double", Double.class);  
  15.     registerAlias("float", Float.class);  
  16.     registerAlias("boolean", Boolean.class);  
  17.   
  18.     registerAlias("byte[]", Byte[].class);  
  19.     registerAlias("long[]", Long[].class);  
  20.     registerAlias("short[]", Short[].class);  
  21.     registerAlias("int[]", Integer[].class);  
  22.     registerAlias("integer[]", Integer[].class);  
  23.     registerAlias("double[]", Double[].class);  
  24.     registerAlias("float[]", Float[].class);  
  25.     registerAlias("boolean[]", Boolean[].class);  
  26.   
  27.     registerAlias("_byte"byte.class);  
  28.     registerAlias("_long"long.class);  
  29.     registerAlias("_short"short.class);  
  30.     registerAlias("_int"int.class);  
  31.     registerAlias("_integer"int.class);  
  32.     registerAlias("_double"double.class);  
  33.     registerAlias("_float"float.class);  
  34.     registerAlias("_boolean"boolean.class);  
  35.   
  36.     registerAlias("_byte[]"byte[].class);  
  37.     registerAlias("_long[]"long[].class);  
  38.     registerAlias("_short[]"short[].class);  
  39.     registerAlias("_int[]"int[].class);  
  40.     registerAlias("_integer[]"int[].class);  
  41.     registerAlias("_double[]"double[].class);  
  42.     registerAlias("_float[]"float[].class);  
  43.     registerAlias("_boolean[]"boolean[].class);  
  44.   
  45.     registerAlias("date", Date.class);  
  46.     registerAlias("decimal", BigDecimal.class);  
  47.     registerAlias("bigdecimal", BigDecimal.class);  
  48.     registerAlias("biginteger", BigInteger.class);  
  49.     registerAlias("object", Object.class);  
  50.   
  51.     registerAlias("date[]", Date[].class);  
  52.     registerAlias("decimal[]", BigDecimal[].class);  
  53.     registerAlias("bigdecimal[]", BigDecimal[].class);  
  54.     registerAlias("biginteger[]", BigInteger[].class);  
  55.     registerAlias("object[]", Object[].class);  
  56.   
  57.     registerAlias("map", Map.class);  
  58.     registerAlias("hashmap", HashMap.class);  
  59.     registerAlias("list", List.class);  
  60.     registerAlias("arraylist", ArrayList.class);  
  61.     registerAlias("collection", Collection.class);  
  62.     registerAlias("iterator", Iterator.class);  
  63.   
  64.     registerAlias("ResultSet", ResultSet.class);  
  65.   }  
  66.   
  67.   @SuppressWarnings("unchecked")  
  68.   // throws class cast exception as well if types cannot be assigned  
  69.   /* 通过别名来找到具体的类**/  
  70.   public <T> Class<T> resolveAlias(String string) {  
  71.     try {  
  72.       if (string == null) {  
  73.         return null;  
  74.       }  
  75.       // issue #748  
  76.       String key = string.toLowerCase(Locale.ENGLISH);  
  77.       Class<T> value;  
  78.       if (TYPE_ALIASES.containsKey(key)) {  
  79.         value = (Class<T>) TYPE_ALIASES.get(key);  
  80.       } else {  
  81.         value = (Class<T>) Resources.classForName(string);  
  82.       }  
  83.       return value;  
  84.     } catch (ClassNotFoundException e) {  
  85.       throw new TypeException("Could not resolve type alias '" + string + "'.  Cause: " + e, e);  
  86.     }  
  87.   }  
  88.   /* 通过包名注册类**/  
  89.   public void registerAliases(String packageName){  
  90.     registerAliases(packageName, Object.class);  
  91.   }  
  92.   /* 获得包内的类,除去内部类和接口**/  
  93.   public void registerAliases(String packageName, Class<?> superType){  
  94.     ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();  
  95.     resolverUtil.find(new ResolverUtil.IsA(superType), packageName);  
  96.     Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();  
  97.     for(Class<?> type : typeSet){  
  98.       // Ignore inner classes and interfaces (including package-info.java)  
  99.       // Skip also inner classes. See issue #6  
  100.       if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {  
  101.         registerAlias(type);  
  102.       }  
  103.     }  
  104.   }  
  105.   /* 注册类**/  
  106.   public void registerAlias(Class<?> type) {  
  107.     String alias = type.getSimpleName();  
  108.     Alias aliasAnnotation = type.getAnnotation(Alias.class);  
  109.     if (aliasAnnotation != null) {  
  110.       alias = aliasAnnotation.value();  
  111.     }   
  112.     registerAlias(alias, type);  
  113.   }  
  114.   /* 注册类包括别名和类**/  
  115.   public void registerAlias(String alias, Class<?> value) {  
  116.     if (alias == null) {  
  117.       throw new TypeException("The parameter alias cannot be null");  
  118.     }  
  119.     // issue #748  
  120.     String key = alias.toLowerCase(Locale.ENGLISH);  
  121.     if (TYPE_ALIASES.containsKey(key) && TYPE_ALIASES.get(key) != null && !TYPE_ALIASES.get(key).equals(value)) {  
  122.       throw new TypeException("The alias '" + alias + "' is already mapped to the value '" + TYPE_ALIASES.get(key).getName() + "'.");  
  123.     }  
  124.     TYPE_ALIASES.put(key, value);  
  125.   }  
  126.   /* 注册类包括别名和类名**/  
  127.   public void registerAlias(String alias, String value) {  
  128.     try {  
  129.       registerAlias(alias, Resources.classForName(value));  
  130.     } catch (ClassNotFoundException e) {  
  131.       throw new TypeException("Error registering type alias "+alias+" for "+value+". Cause: " + e, e);  
  132.     }  
  133.   }  
  134.     
  135.   /** 
  136.    * @since 3.2.2 
  137.    */  
  138.   public Map<String, Class<?>> getTypeAliases() {  
  139.     return Collections.unmodifiableMap(TYPE_ALIASES);  
  140.   }  
  141.   
  142. }  

通过上面的源码我们可以看到,它默认注册了一些基本的类型基本类和包装类,然后我们可以调用registerAliases来注册其他类的别名。

(3)刚才我们看到了TypeAliasRegistry.registerAliases()函数会登记别名及类名,我们也可以看到TypeAliasRegistry通过了resolveAlias函数来让我们通过别名alias来获取实际的类,源码如下:

[java] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. /* 通过别名来找到具体的类**/  
  2.   public <T> Class<T> resolveAlias(String string) {  
  3.     try {  
  4.       if (string == null) {  
  5.         return null;  
  6.       }  
  7.       // issue #748  
  8.       String key = string.toLowerCase(Locale.ENGLISH);  
  9.       Class<T> value;  
  10.       if (TYPE_ALIASES.containsKey(key)) {  
  11.         value = (Class<T>) TYPE_ALIASES.get(key);  
  12.       } else {  
  13.         value = (Class<T>) Resources.classForName(string);  
  14.       }  
  15.       return value;  
  16.     } catch (ClassNotFoundException e) {  
  17.       throw new TypeException("Could not resolve type alias '" + string + "'.  Cause: " + e, e);  
  18.     }  
  19.   }  

总结:这样我们就对Mybatis的typaAlias的实现机制就有了一个简单的了解,其实简单说就是创建了一个Map<string,Class<?>>,解析mybatis的配置文件,将alias元素的值作为Map的key,通过反射机制获得的type元素对应的类名的类作为Map的value值,在真正使用时通过alias别名来获取真正的类。


-------------

更多的Java,Angular,Android,大数据,J2EE,Python,数据库,Linux,Java架构师,:

http://www.cnblogs.com/zengmiaogen/p/7083694.html


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/538654.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java中Synchronized的用法

2019独角兽企业重金招聘Python工程师标准>>> 《编程思想之多线程与多进程(1)——以操作系统的角度述说线程与进程》一文详细讲述了线程、进程的关系及在操作系统中的表现&#xff0c;这是多线程学习必须了解的基础。本文将接着讲一下Java线程同步中的一个重要的概念…

concat特征融合_MSFNet:多重空间融合网络进行实时语义分割(北航和旷视联合提出)...

作者&#xff1a;Tom HardyDate&#xff1a;2020-02-01来源&#xff1a;MSFNet:多重空间融合网络进行实时语义分割&#xff08;北航和旷视联合提出&#xff09;原文链接&#xff1a;https://arxiv.org/abs/1911.07217主要内容实时语义分割是一项具有挑战性的任务&#xff0c;因…

wifi信号手机测试软件,专业的WiFi检测工具有哪些?如何解决wifi信号不好?

原标题&#xff1a;专业的WiFi检测工具有哪些&#xff1f;如何解决wifi信号不好&#xff1f;有朋友wifi测试软件有哪些&#xff1f;WiFi信号和声音一样&#xff0c;强弱都是可以测量的&#xff0c;检测WiFi的方法有很多&#xff0c;作为普通的家庭用户&#xff0c;我们有时需要…

python创建数组与列表_python基础(三):数组和列表

下面是小凰凰的简介&#xff0c;看下吧&#xff01; &#x1f497;人生态度&#xff1a;珍惜时间&#xff0c;渴望学习&#xff0c;热爱音乐&#xff0c;把握命运&#xff0c;享受生活 &#x1f497;学习技能&#xff1a;网络 -> 云计算运维 -> python全栈( 当前正在学习…

Mybatis之typeAlias配置的3种方法

原文链接&#xff1a;http://www.cnblogs.com/lxcmyf/p/6444120.html ------------------------------- 扩展阅读&#xff1a;http://blog.csdn.net/zengmingen/article/details/70163420 ------------------------------------ 1.定义别名&#xff1a; <typeAliases>…

计算机函数两个表格找相同,wps筛选出两个表格中的重复项(countif 函数简单使用)【已解决】...

假设&#xff0c;有以下两个表格文件。为了掩饰&#xff0c;数据就几个。AB两个表格&#xff0c;现在要做的是从A表格中&#xff0c;去除跟B表格重复的内容&#xff0c;只保留剩余的数据。第一步&#xff0c;先把B表格中的 蔬菜名称 那一列&#xff0c;复制到A表格中。(如果数据…

python常用正则表达式_Python3常用正则表达式

正则表达式速查表 字符 描述 \ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如&#xff0c;“n“匹配字符”n“。”\n“匹配一个换行符。串行”\\“匹配”\“而”\(“则匹配”(“。 ^ 匹配输入字符串的开始位置。如果设置了RegExp…

Spring Cloud 学习笔记(一) 之服务治理模块Spring Cloud Eureka 搭建注册中心

2019独角兽企业重金招聘Python工程师标准>>> 关于springboot的学习请参考前面的文章 接下来我们会开启一系列关于springcloud的学习文章。 一、概念 首先我们看下官方的解释 Service Discovery is one of the key tenets of a microservice-based architecture. Try…

java分治法求数列的最大子段和_同事为进大厂天天刷Java面试题,面试却履败!究其原因竟是它在捣鬼。...

写在前面疫情过后&#xff0c;招聘与求职受影响到底有多大&#xff1f;我不知道&#xff0c;但我的真实感受是&#xff0c;即使有疫情的影响&#xff0c;最近还是持续有朋友来跟我说他们今年工作的新动向。有人跳槽去了大厂&#xff0c;有人下定决心出来创业&#xff0c;也有人…

中国移动wlan优化app-截图

Nokia的wlan优化项目得到了中国移动省公司的认同&#xff0c;成为了重点项目&#xff0c;转移了其他项目组开发。 我单独负责开发Android端app。还没开发完&#xff0c;源码也移交了&#xff0c;不再继续参与开发。 新任务是负责现有平台从Oracle转为大数据。截图纪念下近半个…

linux软件安装管理

Linux软件安装管理 TonyLinux系统工程师难度初级 时长 3小时 6分 学习人数64016 综合评分9.8收藏上面是linux 的源代码安装包 linux有两种类型的软件安装方式&#xff1a; 1、源代码安装 这种方式的软件安装&#xff0c;可以指定软件的安装目录&#xff0c;软件的运行效率高&am…

ts语音自建服务器,自建TeamSpeak语音服务器,免费提供给专注游戏的玩家使用!...

先提一句&#xff0c;带过节奏的云玩家 可以滚了&#xff01;​​​以下内容更新于2020/5/22 15:30&#xff1a;​根据 洛杉矶湖人名宿孙悦 ​的提醒&#xff0c;不推荐下载ts1.cn的盗版客户端&#xff0c;也不推荐俱乐部或者各位玩家租用ts1.cn的盗版服务器。具体可查看帖子 h…

电子电器架构刷写方案——General Flash Bootloader

电子电器架构刷写方案——General Flash Bootloader 我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 注&#xff1a;文章1万字左右&#xff0c;深度思考者入&#xff01;&#xff01;&#xff01; 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免…

python心理学实验程序_心理学实验程序编程(python)

任务一&#xff1a;实现简单的屏幕的颜色之间的切换 importpygamefrom pygame.locals import *pygame.init() win pygame.display.set_mode((800,600),DOUBLEBUF|HWSURFACE)for i in range(10): win.fill((0,255,0))if i%20: win.fill((255,0,0)) pygame.time.wait(500) pygame…

Hbase介绍

1、为什么出现hbase&#xff1f;hadoop 的NameNode适合大文件&#xff0c;不适合小文件。HDFS不适合大量小文件的存储&#xff0c;因namenode将文件系统的元数据存放在内存中&#xff0c;因此存储的文件数目受限于 namenode的内存大小。HDFS中每个文件、目录、数据块占用150Byt…

math 向上取整_自我说明:关于Math和File类的具体说明.

Math类:Math类&#xff0c;不允许有子类&#xff0c;它直接继承于object.Math类包含执行基本数字运算的方法.如基本指数&#xff0c;对数&#xff0c;平方根和三角函数.Math的基本方法&#xff1a;System.out.pintln(“1.绝对值&#xff1a;”Math.abs(16)”t”Math.abs(-16)”…

眼图 非差分线_LVDS低电压差分信号简介

LVDS低电压差分信号简介1. 名词解释1.1. 背景随着数据传输速率越来越高&#xff0c;现在计算机系统中的数据传输接口基本上都串行化了&#xff0c;像USB、PCIe、SATA、DP等等外部总线将并行总线挤压到只剩下内存总线这个最后的堡垒。当然&#xff0c;就算是并行传输总线最后的倔…

无内存在优盘可以启动计算机吗,没有U盘不要紧,内存卡做启动盘装Win7方法

现在最流行的win7系统安装方法大多以U盘来安装&#xff0c;那么如果你没有U盘呢&#xff1f;为了安装个Win7系统是不是要去买个U盘&#xff1f;当然不用&#xff0c;如果你还有空闲不用的手机内存卡&#xff0c;那么也是可以制作U盘启动盘来安装Win7系统的。准备工具&#xff1…

spyder python调试_使用spyder编译器单步调试python

1、将需要进行单步调试的函数在脚本中进行调用&#xff08;十分重要的一步&#xff09;。由于python是解释型语言&#xff0c;在进行单步调试的时候需要告诉系统你使用了这个函数&#xff0c;单步调试才会进入你所需要调式的函数。如下图所示&#xff0c;我们定义了createDataS…

label qt 自动换行_QT编写一个登录界面

前言继上篇&#xff1a;一起学Qt之基础篇---入门今天上手实操用QT编写一个登录界面~系统权限这个词大家肯定不陌生&#xff0c;你进入一个网站也是&#xff0c;如果不登录&#xff0c;就是以游客的身份进去的&#xff0c;要想看到某些信息肯定需要进行登录&#xff0c;更完善的…