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.pswp.cn/news/538654.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/538654.shtml
英文地址,請注明出處:http://en.pswp.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>…

PHP 開啟或關閉錯誤提示

如果不具備修改 php.ini 的權限&#xff0c;可以如下&#xff1a; // 只需在php文件中加入這兩句即可開啟PHP錯誤提示ini_set("display_errors", "On"); error_reporting(E_ALL | E_STRICT); 如果具備修改 php.ini 權限的話&#xff0c;如下即可&#xff…

python 無頭模式_Python + Selenium(二十五)無頭模式 headless

所謂瀏覽器的無頭模式headless&#xff0c;就是瀏覽器在運行時處于后臺操作的模式&#xff0c;不會看到瀏覽器打開&#xff0c;也就不會干擾你手頭的工作。對于自動化測試和網絡爬蟲都有很大的價值。早期我們使用 phantomJS 瀏覽器來實現這種模式&#xff0c;隨著 Chrome 和 Fi…

計算機函數兩個表格找相同,wps篩選出兩個表格中的重復項(countif 函數簡單使用)【已解決】...

假設&#xff0c;有以下兩個表格文件。為了掩飾&#xff0c;數據就幾個。AB兩個表格&#xff0c;現在要做的是從A表格中&#xff0c;去除跟B表格重復的內容&#xff0c;只保留剩余的數據。第一步&#xff0c;先把B表格中的 蔬菜名稱 那一列&#xff0c;復制到A表格中。(如果數據…

區分 JSON 字符串與JSON對象

&#xff08;1&#xff09;JSON 對象是滿足 JSON 數據格式的 JS 對象例如&#xff1a; {name:"abc"}最正規的 JSON 數據是連屬性名稱都要被包括起來的例如&#xff1a; {"name":"abc"}&#xff08;2&#xff09;JSON 格式的字符串的關鍵問題-- 它…

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…

shell 進入hadoop_Hadoop關于HDFS的基本操作(Shell命令)

在這里我給大家繼續分享一些關于hdfs分布式文件的經驗哈&#xff0c;其中包括一些hdfs的基本的shell命令的操作&#xff0c;再加上hdfs java程序設計。在前面我已經寫了關于如何去搭建hadoop這樣一個大數據平臺&#xff0c;還沒搭好環境的童鞋可以轉到我寫的這篇文章hadoop在ub…

材料凝固計算機模擬,金屬基復合材料凝固過程計算機模擬Ⅲ.pdf

金屬基復合材料凝固過程計算機模擬Ⅲ,金屬基復合材料,金屬復合材料,金屬陶瓷復合材料,金屬基復合材料ppt,金屬基復合材料導論,無機非金屬基復合材料,雙金屬復合材料,金屬基陶瓷復合材料,金屬基復合材料的應用第 卷第 期"" $ 南方冶金學院學報 W;(#""VB;#$年…

java分治法求數列的最大子段和_同事為進大廠天天刷Java面試題,面試卻履敗!究其原因竟是它在搗鬼。...

寫在前面疫情過后&#xff0c;招聘與求職受影響到底有多大&#xff1f;我不知道&#xff0c;但我的真實感受是&#xff0c;即使有疫情的影響&#xff0c;最近還是持續有朋友來跟我說他們今年工作的新動向。有人跳槽去了大廠&#xff0c;有人下定決心出來創業&#xff0c;也有人…

中國移動wlan優化app-截圖

Nokia的wlan優化項目得到了中國移動省公司的認同&#xff0c;成為了重點項目&#xff0c;轉移了其他項目組開發。 我單獨負責開發Android端app。還沒開發完&#xff0c;源碼也移交了&#xff0c;不再繼續參與開發。 新任務是負責現有平臺從Oracle轉為大數據。截圖紀念下近半個…

soapui和cxf的卻別_根據wsdl文件用soapUi快速構建webService服務(有圖有真相)

最近公司業務上使用webservice 頻繁。由于之前都是自己建立webservice 自己定義提供幫對方服務&#xff0c;現在則相反需求都是根據人家提供的wsdl 文件來生成 我們系統必須提供的接口。剛起初不知道如何生成soapui調用wsdl需要安全驗證&#xff0c;為了一個webservice 服務&am…

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…

hbase多master和動態添加節點

1、多個master節點。 在reginserver節點上使用命令&#xff1a; hbase-daemon.sh start master 在nbdo3機器上啟動主備后&#xff0c;查看nbdo3機器上master產生的日志&#xff1a; 2017-04-08 09:37:52,471 INFO [nbdo3:16000.activeMasterManager] master.ActiveMasterMa…

電子電器架構刷寫方案——General Flash Bootloader

電子電器架構刷寫方案——General Flash Bootloader 我是穿拖鞋的漢子&#xff0c;魔都中堅持長期主義的汽車電子工程師。 注&#xff1a;文章1萬字左右&#xff0c;深度思考者入&#xff01;&#xff01;&#xff01; 老規矩&#xff0c;分享一段喜歡的文字&#xff0c;避免…