Mybatis中TypeAliasRegistry的作用及使用方法
一、引入類型別名
當(dāng)配置 XML 文件,需要指明Java類型時,類型別名可替代Java類型的全名,一般會設(shè)置一個簡單縮寫的類型別名去替代它,用于XML配置,以降低冗余的全限定類名書寫。(說白了其作用就是偷懶)
下面是使用全限定類名指定的配置:
<select id="selectAll" resultType="com.ncpowernode.mybatis.bean.User"> select * from t_user; </select>
當(dāng)在核心配置文件中配置完后:
<typeAliases> <! --<package name="com.ncpowernode .mybatis.bean" />--> <typeAlias type="com.ncpowernode .mybatis.bean. User"/> </typeAliases>
即可寫成下面的形式:
<select id="selectAll" resultType="user"> select * from t_user; </select>
二、typeAlias的三種配置方式
type屬性和alias屬性雙搭
<typeAlias type="com.ncpowernode.mybatis.bean.User" alias="user"/>
直接寫type屬性指定全限定類名,底層會利用該類的simpleName
去當(dāng)作這個alias。
<typeAlias type="com.ncpowernode.mybatis.bean.User"/>
直接配置包標(biāo)簽,使得指定包下的所有類都進行別名配置。
<package name="com.ncpowernode.mybatis.bean"/>
三、TypeAliasRegistry源碼分析
三種配置方式源碼解析
Mybatis通過TypeAliasRegistry
對象實現(xiàn)對別名的封裝,實現(xiàn)別名對應(yīng)Java類型的校驗。TypeAliasRegistry類中是用一Map成員對象實現(xiàn)上面封裝效果的。
public class TypeAliasRegistry { // key對應(yīng)著別名,Class對應(yīng)著全限定類名轉(zhuǎn)換的Class對象 private final Map<String, Class<?>> typeAliases = new HashMap<>(); }
解析核心配置文件時候支持上面提到的三種設(shè)置別名的方式,那自然底層實現(xiàn)也存在三種,但萬變不理其中,最后跳轉(zhuǎn)到的代碼(核心方法)如下所示:
public void registerAlias(String alias, Class<?> value) { //判斷別名是否為空 if (alias == null) { throw new TypeException("The parameter alias cannot be null"); } // 將別名都轉(zhuǎn)換為小寫存儲,利于后續(xù)進行校驗 String key = alias.toLowerCase(Locale.ENGLISH); // 從這段代碼可以知道別名可以支持多個對應(yīng)一個Class對象 if (typeAliases.containsKey(key) && typeAliases.get(key) != null && !typeAliases.get(key).equals(value)) { throw new TypeException( "The alias '" + alias + "' is already mapped to the value '" + typeAliases.get(key).getName() + "'."); } // 封裝到Map中 typeAliases.put(key, value); }
下面對三種方式源碼進行解析
第一種:type和alias屬性雙用(直接跳轉(zhuǎn)到上面核心方法)
public void registerAlias(String alias, String value) { registerAlias(alias, Resources.classForName(value)); }
第二種:僅用type屬性(熟知的簡單類名,為什么是簡單類名當(dāng)作別名下面的代碼很好的體現(xiàn)出來了,還有一種設(shè)置別名的方式是使用@Alias注解,但小編本人不喜歡用)
public void registerAlias(Class<?> type) { // 獲取類中的簡單類名稱,充當(dāng)別名 String alias = type.getSimpleName(); // 如果在對應(yīng)類上用了@Alias注解的話,那對應(yīng)的是@Alias注解中的value屬性值 // 但小編不建議用,出錯了感覺不好排查 Alias aliasAnnotation = type.getAnnotation(Alias.class); if (aliasAnnotation != null) { alias = aliasAnnotation.value(); } // 進行封裝 registerAlias(alias, type); }
第三種:使用package標(biāo)簽(常用)
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) { // 對應(yīng)的類不能是匿名類/接口 if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) { // 本質(zhì)是使用第二種方式 registerAlias(type); } } }
校驗過程
通過閱讀下面源碼可以知道:
- 為什么使用別名的時候各個字符不區(qū)分大小寫;
- 為什么使用別名也行,使用全限定類名也行。
public <T> Class<T> resolveAlias(String string) { try { // 判斷傳來的別名(也可能是全限定類名)不為空 if (string == null) { return null; } // 解析的時候都會轉(zhuǎn)換成小寫 // 這就是為什么使用別名的時候別名字母小寫大寫無所謂 String key = string.toLowerCase(Locale.ENGLISH); Class<T> value; if (typeAliases.containsKey(key)) {// 通過別名查找對應(yīng)的value(Class對象) value = (Class<T>) typeAliases.get(key); } else {// 無別名就當(dāng)作全限定類名處理,不存在就會拋出下面的異常 value = (Class<T>) Resources.classForName(string); } // 返回結(jié)果Class對象 return value; } catch (ClassNotFoundException e) { throw new TypeException("Could not resolve type alias '" + string + "'. Cause: " + e, e); } }
Mybatis默認的別名配置
Mybatis 在初始化Configuration對象的時候自身配置了一些Java類型的類型別名。如下所示:
這是Configuration類中TypeAliasRegistry成員初始化創(chuàng)建對象時候進行的配置
// TypeAliasRegistry類構(gòu)造器初始化 public TypeAliasRegistry() { registerAlias("string", String.class); registerAlias("byte", Byte.class); registerAlias("char", Character.class); registerAlias("character", Character.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("char[]", Character[].class); registerAlias("character[]", Character[].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("_char", char.class); registerAlias("_character", char.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("_char[]", char[].class); registerAlias("_character[]", char[].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); }
這是Configuration對象創(chuàng)建時候的別名配置
public Configuration() { typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class); typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class); typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class); typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class); typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class); typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class); typeAliasRegistry.registerAlias("FIFO", FifoCache.class); typeAliasRegistry.registerAlias("LRU", LruCache.class); typeAliasRegistry.registerAlias("SOFT", SoftCache.class); typeAliasRegistry.registerAlias("WEAK", WeakCache.class); typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class); typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class); typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class); typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class); typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class); typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class); typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class); typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class); typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class); typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class); typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class); typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class); }
這些都是Mybatis框架會配置好的,你可以直接使用。
四、總結(jié)
TypeAliasRegistry 類完成的別名機制,總的來說源碼還是比較簡單的,一個Map對象封裝起來的就完成了。解析核心配置文件擴大別名使用,有懶就偷。
到此這篇關(guān)于Mybatis中TypeAliasRegistry的作用及使用方法的文章就介紹到這了,更多相關(guān)Mybatis TypeAliasRegistry內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java調(diào)用微信客服消息實現(xiàn)發(fā)貨通知的方法詳解
這篇文章主要介紹了Java調(diào)用微信客服消息實現(xiàn)發(fā)貨通知的方法,結(jié)合實例形式詳細分析了java針對微信接口調(diào)用的原理、調(diào)用方法與相關(guān)注意事項,需要的朋友可以參考下2017-08-08WMTS中TileMatrix與ScaleDenominator淺析
這篇文章主要為大家介紹了WMTS中TileMatrix與ScaleDenominator淺析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03使Java的JButton文字隱藏功能的實現(xiàn)(不隱藏按鈕的前提)
這篇文章主要介紹了使Java的JButton文字隱藏功能的實現(xiàn)(不隱藏按鈕的前提),本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01詳解Java中格式化日期的DateFormat與SimpleDateFormat類
DateFormat其本身是一個抽象類,SimpleDateFormat 類是DateFormat類的子類,一般情況下來講DateFormat類很少會直接使用,而都使用SimpleDateFormat類完成,下面我們具體來看一下兩個類的用法:2016-05-05