原文鏈接:http://blog.csdn.net/qq924862077/article/details/52612589
----------------------------------
在Mybatis編程中我們經常會用到將某個bean作為參數類型parameterType或者結果返回值類型ResultType,所以很多時候我們需要把完成的Bean的包名在mapper文件中寫上,如下:

- <select?id="selectUser"?parameterType="com.dy.entity.User"?resultType="com.dy.entity.User">????
- ????select?*?from?user?where?c_id=#{id}????
- </select>????
Mybatis給我們提供了一種叫別名的機制,意思就是對某個具體的類設置別名,在mybatis的配置文件中配置如下:

- <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可以寫成如下格式:

- <select?id="selectUser"?parameterType="user"?resultType="user">????
- ????select?*?from?user?where?c_id=#{id}????
- </select>????
這樣就可以在使用某個bean時使用別名就可以了,不需要寫完成的包名+類名
接下來我們介紹TypeAlias別名的實現機制(1)我們在mybatis的配置文件中配置了typeAliases,我們首先分析XMLConfigBuilder類中對于typeAliases的解析,源碼如下:

- //類別名解析??
- ??private?void?typeAliasesElement(XNode?parent)?{??
- ????if?(parent?!=?null)?{??
- ??????for?(XNode?child?:?parent.getChildren())?{??
- ????????//如果子節點是package,那么就獲取package節點的name屬性??
- ????????if?("package".equals(child.getName()))?{??
- ??????????String?typeAliasPackage?=?child.getStringAttribute("name");??
- ??????????configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);??
- ????????}?else?{??
- ????????//如果子節點是typeAlias節點,那么就獲取alias屬性和type的屬性??
- ??????????String?alias?=?child.getStringAttribute("alias");??
- ??????????String?type?=?child.getStringAttribute("type");??
- ??????????try?{??
- ????????????//通過type的值來加載獲得類??
- ????????????Class<?>?clazz?=?Resources.classForName(type);??
- ????????????if?(alias?==?null)?{??
- ????????????//typeAliasRegistry會進行別名注冊??
- ??????????????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,詳看源碼如下:

- //其實就是一個map結構,用來對象key別名和value具體的類??
- 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")??
- ??//?throws?class?cast?exception?as?well?if?types?cannot?be?assigned??
- ??/*?通過別名來找到具體的類**/??
- ??public?<T>?Class<T>?resolveAlias(String?string)?{??
- ????try?{??
- ??????if?(string?==?null)?{??
- ????????return?null;??
- ??????}??
- ??????//?issue?#748??
- ??????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){??
- ??????//?Ignore?inner?classes?and?interfaces?(including?package-info.java)??
- ??????//?Skip?also?inner?classes.?See?issue?#6??
- ??????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");??
- ????}??
- ????//?issue?#748??
- ????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);??
- ????}??
- ??}??
- ????
- ??/**?
- ???*?@since?3.2.2?
- ???*/??
- ??public?Map<String,?Class<?>>?getTypeAliases()?{??
- ????return?Collections.unmodifiableMap(TYPE_ALIASES);??
- ??}??
- ??
- }??
通過上面的源碼我們可以看到,它默認注冊了一些基本的類型基本類和包裝類,然后我們可以調用registerAliases來注冊其他類的別名。
(3)剛才我們看到了TypeAliasRegistry.registerAliases()函數會登記別名及類名,我們也可以看到TypeAliasRegistry通過了resolveAlias函數來讓我們通過別名alias來獲取實際的類,源碼如下:

- /*?通過別名來找到具體的類**/??
- ??public?<T>?Class<T>?resolveAlias(String?string)?{??
- ????try?{??
- ??????if?(string?==?null)?{??
- ????????return?null;??
- ??????}??
- ??????//?issue?#748??
- ??????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