原文鏈接:http://blog.csdn.net/qq924862077/article/details/52612589
----------------------------------
在Mybatis編程中我們經常會用到將某個bean作為參數類型parameterType或者結果返回值類型ResultType,所以很多時候我們需要把完成的Bean的包名在mapper文件中寫上,如下:
[html]?view plaincopy print?
<select?id="selectUser"?parameterType="com.dy.entity.User"?resultType="com.dy.entity.User">???? ????select?*?from?user?where?c_id=#{id}???? </select>????
Mybatis給我們提供了一種叫別名的機制,意思就是對某個具體的類設置別名,在mybatis的配置文件中配置如下:
[html]?view plaincopy print?
<configuration>?? ????<typeAliases>?? ??????<!--?? ??????通過package,?可以直接指定package的名字,?mybatis會自動掃描你指定包下面的javabean,?? ??????并且默認設置一個別名,默認的名字為:?javabean?的首字母小寫的非限定類名來作為它的別名。?? ??????也可在javabean?加上注解@Alias?來自定義別名,?例如:?@Alias(user)??? ??????<package?name="com.dy.entity"/>?? ???????-->?
??????<typeAlias?alias="user"?type="com.dy.entity.User"/>??
??</typeAliases>?? ???? ??......?? ???? </configuration>??
這樣之后mapper文件中的select可以寫成如下格式:
[html]?view plaincopy print?
<select?id="selectUser"?parameterType="user"?resultType="user">???? ????select?*?from?user?where?c_id=#{id}???? </select>????
這樣就可以在使用某個bean時使用別名就可以了,不需要寫完成的包名+類名
接下來我們介紹TypeAlias別名的實現機制
(1)我們在mybatis的配置文件中配置了typeAliases,我們首先分析XMLConfigBuilder類中對于typeAliases的解析,源碼如下:
[java]?view plaincopy print?
?? ??private?void?typeAliasesElement(XNode?parent)?{?? ????if?(parent?!=?null)?{?? ??????for?(XNode?child?:?parent.getChildren())?{?? ?????????? ????????if?("package".equals(child.getName()))?{?? ??????????String?typeAliasPackage?=?child.getStringAttribute("name");?? ??????????configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);?? ????????}?else?{?? ?????????? ??????????String?alias?=?child.getStringAttribute("alias");?? ??????????String?type?=?child.getStringAttribute("type");?? ??????????try?{?? ?????????????? ????????????Class<?>?clazz?=?Resources.classForName(type);?? ????????????if?(alias?==?null)?{?? ?????????????? ??????????????typeAliasRegistry.registerAlias(clazz);?? ????????????}?else?{?? ??????????????typeAliasRegistry.registerAlias(alias,?clazz);?? ????????????}?? ??????????}?catch?(ClassNotFoundException?e)?{?? ????????????throw?new?BuilderException("Error?registering?typeAlias?for?'"?+?alias?+?"'.?Cause:?"?+?e,?e);?? ??????????}?? ????????}?? ??????}?? ????}??
通過分析源碼我們可以得知,解析alias來獲得別名,解析type元素來獲得類名,通過Resources.classForName(type)獲得類信息,然后通過typeAliasRegistry.registerAlias(alias, clazz)將類別名注冊到typeAliasRegistry中,這樣就完成了mybatis中配置文件的解析。
(3)TypeAliasRegistry:是用來記錄別名alias和類clazz之間的對應關系的,它可以看做是一個Map,alias作為key,類名作為value,詳看源碼如下:
[java]?view plaincopy print?
?? public?class?TypeAliasRegistry?{?? ?? ??private?final?Map<String,?Class<?>>?TYPE_ALIASES?=?new?HashMap<String,?Class<?>>();?? ?? ??public?TypeAliasRegistry()?{?? ????registerAlias("string",?String.class);?? ?? ????registerAlias("byte",?Byte.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("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("_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("_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);?? ??}?? ?? ??@SuppressWarnings("unchecked")?? ???? ???? ??public?<T>?Class<T>?resolveAlias(String?string)?{?? ????try?{?? ??????if?(string?==?null)?{?? ????????return?null;?? ??????}?? ???????? ??????String?key?=?string.toLowerCase(Locale.ENGLISH);?? ??????Class<T>?value;?? ??????if?(TYPE_ALIASES.containsKey(key))?{?? ????????value?=?(Class<T>)?TYPE_ALIASES.get(key);?? ??????}?else?{?? ????????value?=?(Class<T>)?Resources.classForName(string);?? ??????}?? ??????return?value;?? ????}?catch?(ClassNotFoundException?e)?{?? ??????throw?new?TypeException("Could?not?resolve?type?alias?'"?+?string?+?"'.??Cause:?"?+?e,?e);?? ????}?? ??}?? ???? ??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?void?registerAlias(Class<?>?type)?{?? ????String?alias?=?type.getSimpleName();?? ????Alias?aliasAnnotation?=?type.getAnnotation(Alias.class);?? ????if?(aliasAnnotation?!=?null)?{?? ??????alias?=?aliasAnnotation.value();?? ????}??? ????registerAlias(alias,?type);?? ??}?? ???? ??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);?? ????if?(TYPE_ALIASES.containsKey(key)?&&?TYPE_ALIASES.get(key)?!=?null?&&?!TYPE_ALIASES.get(key).equals(value))?{?? ??????throw?new?TypeException("The?alias?'"?+?alias?+?"'?is?already?mapped?to?the?value?'"?+?TYPE_ALIASES.get(key).getName()?+?"'.");?? ????}?? ????TYPE_ALIASES.put(key,?value);?? ??}?? ???? ??public?void?registerAlias(String?alias,?String?value)?{?? ????try?{?? ??????registerAlias(alias,?Resources.classForName(value));?? ????}?catch?(ClassNotFoundException?e)?{?? ??????throw?new?TypeException("Error?registering?type?alias?"+alias+"?for?"+value+".?Cause:?"?+?e,?e);?? ????}?? ??}?? ???? ??? ? ?? ??public?Map<String,?Class<?>>?getTypeAliases()?{?? ????return?Collections.unmodifiableMap(TYPE_ALIASES);?? ??}?? ?? }??
通過上面的源碼我們可以看到,它默認注冊了一些基本的類型基本類和包裝類,然后我們可以調用registerAliases來注冊其他類的別名。
(3)剛才我們看到了TypeAliasRegistry.registerAliases()函數會登記別名及類名,我們也可以看到TypeAliasRegistry通過了resolveAlias函數來讓我們通過別名alias來獲取實際的類,源碼如下:
[java]?view plaincopy print?
?? ??public?<T>?Class<T>?resolveAlias(String?string)?{?? ????try?{?? ??????if?(string?==?null)?{?? ????????return?null;?? ??????}?? ???????? ??????String?key?=?string.toLowerCase(Locale.ENGLISH);?? ??????Class<T>?value;?? ??????if?(TYPE_ALIASES.containsKey(key))?{?? ????????value?=?(Class<T>)?TYPE_ALIASES.get(key);?? ??????}?else?{?? ????????value?=?(Class<T>)?Resources.classForName(string);?? ??????}?? ??????return?value;?? ????}?catch?(ClassNotFoundException?e)?{?? ??????throw?new?TypeException("Could?not?resolve?type?alias?'"?+?string?+?"'.??Cause:?"?+?e,?e);?? ????}?? ??}??
總結:這樣我們就對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
總結
以上是生活随笔為你收集整理的Mybatis源码之(TypeAliasRegistry)TypeAlias别名实现机制的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。