Mybatis中TypeAliasRegistry的作用及使用方法
一、引入類(lèi)型別名
當(dāng)配置 XML 文件,需要指明Java類(lèi)型時(shí),類(lèi)型別名可替代Java類(lèi)型的全名,一般會(huì)設(shè)置一個(gè)簡(jiǎn)單縮寫(xiě)的類(lèi)型別名去替代它,用于XML配置,以降低冗余的全限定類(lèi)名書(shū)寫(xiě)。(說(shuō)白了其作用就是偷懶)
下面是使用全限定類(lèi)名指定的配置:
<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>
即可寫(xiě)成下面的形式:
<select id="selectAll" resultType="user">
select * from t_user;
</select>二、typeAlias的三種配置方式
type屬性和alias屬性雙搭
<typeAlias type="com.ncpowernode.mybatis.bean.User" alias="user"/>
直接寫(xiě)type屬性指定全限定類(lèi)名,底層會(huì)利用該類(lèi)的simpleName去當(dāng)作這個(gè)alias。
<typeAlias type="com.ncpowernode.mybatis.bean.User"/>
直接配置包標(biāo)簽,使得指定包下的所有類(lèi)都進(jìn)行別名配置。
<package name="com.ncpowernode.mybatis.bean"/>
三、TypeAliasRegistry源碼分析
三種配置方式源碼解析
Mybatis通過(guò)TypeAliasRegistry對(duì)象實(shí)現(xiàn)對(duì)別名的封裝,實(shí)現(xiàn)別名對(duì)應(yīng)Java類(lèi)型的校驗(yàn)。TypeAliasRegistry類(lèi)中是用一Map成員對(duì)象實(shí)現(xiàn)上面封裝效果的。
public class TypeAliasRegistry {
// key對(duì)應(yīng)著別名,Class對(duì)應(yīng)著全限定類(lèi)名轉(zhuǎn)換的Class對(duì)象
private final Map<String, Class<?>> typeAliases = new HashMap<>();
}解析核心配置文件時(shí)候支持上面提到的三種設(shè)置別名的方式,那自然底層實(shí)現(xiàn)也存在三種,但萬(wàn)變不理其中,最后跳轉(zhuǎn)到的代碼(核心方法)如下所示:
public void registerAlias(String alias, Class<?> value) {
//判斷別名是否為空
if (alias == null) {
throw new TypeException("The parameter alias cannot be null");
}
// 將別名都轉(zhuǎn)換為小寫(xiě)存儲(chǔ),利于后續(xù)進(jìn)行校驗(yàn)
String key = alias.toLowerCase(Locale.ENGLISH);
// 從這段代碼可以知道別名可以支持多個(gè)對(duì)應(yīng)一個(gè)Class對(duì)象
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);
}下面對(duì)三種方式源碼進(jìn)行解析
第一種:type和alias屬性雙用(直接跳轉(zhuǎn)到上面核心方法)
public void registerAlias(String alias, String value) {
registerAlias(alias, Resources.classForName(value));
}第二種:僅用type屬性(熟知的簡(jiǎn)單類(lèi)名,為什么是簡(jiǎn)單類(lèi)名當(dāng)作別名下面的代碼很好的體現(xiàn)出來(lái)了,還有一種設(shè)置別名的方式是使用@Alias注解,但小編本人不喜歡用)
public void registerAlias(Class<?> type) {
// 獲取類(lèi)中的簡(jiǎn)單類(lèi)名稱(chēng),充當(dāng)別名
String alias = type.getSimpleName();
// 如果在對(duì)應(yīng)類(lèi)上用了@Alias注解的話(huà),那對(duì)應(yīng)的是@Alias注解中的value屬性值
// 但小編不建議用,出錯(cuò)了感覺(jué)不好排查
Alias aliasAnnotation = type.getAnnotation(Alias.class);
if (aliasAnnotation != null) {
alias = aliasAnnotation.value();
}
// 進(jìn)行封裝
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<>();
// 獲取包下的類(lèi)Class對(duì)象,僅該目錄下的,子目錄下的類(lèi)對(duì)象不包括
resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();
for (Class<?> type : typeSet) {
// 對(duì)應(yīng)的類(lèi)不能是匿名類(lèi)/接口
if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
// 本質(zhì)是使用第二種方式
registerAlias(type);
}
}
}校驗(yàn)過(guò)程
通過(guò)閱讀下面源碼可以知道:
- 為什么使用別名的時(shí)候各個(gè)字符不區(qū)分大小寫(xiě);
- 為什么使用別名也行,使用全限定類(lèi)名也行。
public <T> Class<T> resolveAlias(String string) {
try {
// 判斷傳來(lái)的別名(也可能是全限定類(lèi)名)不為空
if (string == null) {
return null;
}
// 解析的時(shí)候都會(huì)轉(zhuǎn)換成小寫(xiě)
// 這就是為什么使用別名的時(shí)候別名字母小寫(xiě)大寫(xiě)無(wú)所謂
String key = string.toLowerCase(Locale.ENGLISH);
Class<T> value;
if (typeAliases.containsKey(key)) {// 通過(guò)別名查找對(duì)應(yīng)的value(Class對(duì)象)
value = (Class<T>) typeAliases.get(key);
} else {// 無(wú)別名就當(dāng)作全限定類(lèi)名處理,不存在就會(huì)拋出下面的異常
value = (Class<T>) Resources.classForName(string);
}
// 返回結(jié)果Class對(duì)象
return value;
} catch (ClassNotFoundException e) {
throw new TypeException("Could not resolve type alias '" + string + "'. Cause: " + e, e);
}
}Mybatis默認(rèn)的別名配置
Mybatis 在初始化Configuration對(duì)象的時(shí)候自身配置了一些Java類(lèi)型的類(lèi)型別名。如下所示:
這是Configuration類(lèi)中TypeAliasRegistry成員初始化創(chuàng)建對(duì)象時(shí)候進(jìn)行的配置
// TypeAliasRegistry類(lèi)構(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對(duì)象創(chuàng)建時(shí)候的別名配置
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框架會(huì)配置好的,你可以直接使用。
四、總結(jié)
TypeAliasRegistry 類(lèi)完成的別名機(jī)制,總的來(lái)說(shuō)源碼還是比較簡(jiǎn)單的,一個(gè)Map對(duì)象封裝起來(lái)的就完成了。解析核心配置文件擴(kuò)大別名使用,有懶就偷。
到此這篇關(guān)于Mybatis中TypeAliasRegistry的作用及使用方法的文章就介紹到這了,更多相關(guān)Mybatis TypeAliasRegistry內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot使用Spring Data JPA實(shí)現(xiàn)數(shù)據(jù)庫(kù)操作
Spring Data JPA 是 Spring 基于 Spring Data 框架、在JPA 規(guī)范的基礎(chǔ)上開(kāi)發(fā)的一個(gè)框架,使用 Spring Data JPA 可以極大地簡(jiǎn)化JPA 的寫(xiě)法,本章我們將詳細(xì)介紹在Springboot中使用 Spring Data JPA 來(lái)實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的操作2021-06-06
Java tomcat環(huán)境變量及idea配置解析
這篇文章主要介紹了Java tomcat環(huán)境變量及idea配置解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12
java實(shí)現(xiàn)自動(dòng)售貨機(jī)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)自動(dòng)售貨機(jī),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
SpringBoot自定義注解之實(shí)現(xiàn)AOP切面日志詳解
這篇文章主要為大家詳細(xì)介紹了SpringBoot自定義注解之實(shí)現(xiàn)AOP切面統(tǒng)一打印出入?yún)⑷罩?,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09
Java實(shí)現(xiàn)分頁(yè)的幾種方法詳細(xì)解析
這篇文章主要介紹了Java實(shí)現(xiàn)分頁(yè)的幾種方法詳細(xì)解析,在Java中想實(shí)現(xiàn)分頁(yè)功能有幾種常用的方法,今天我們就來(lái)詳細(xì)解析一下,文中提供了解決思路和部分實(shí)現(xiàn)代碼,需要的朋友可以參考下2023-11-11
IntelliJ IDEA多屏后窗口不顯示問(wèn)題解決方案
這篇文章主要介紹了IntelliJ IDEA多屏后窗口不顯示問(wèn)題解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09

