Hutool開(kāi)發(fā)利器MapProxy類(lèi)使用技巧詳解
概述
Hutool是一個(gè)小而全的Java工具類(lèi)庫(kù),通過(guò)靜態(tài)方法封裝,降低相關(guān)API的學(xué)習(xí)成本,提高工作效率,使Java擁有函數(shù)式語(yǔ)言般的優(yōu)雅,讓Java語(yǔ)言也可以“甜甜的”。
目前公司項(xiàng)目中主要采用Hutool作為項(xiàng)目的工具包,相對(duì)于google的guava, hutool的工具類(lèi)采用中文注釋?zhuān)臃蠂?guó)人使用。所謂知己知彼,我們需要了解Hutool都具有什么樣的功能,才能夠最大化發(fā)揮它的價(jià)值。
本文主要就hutool 5.8.8版本中MapProxy的使用。
場(chǎng)景引入
其實(shí)Map在get的時(shí)候是比較危險(xiǎn)的,你可能不知道它是什么類(lèi)型,需要進(jìn)行強(qiáng)制,舉個(gè)例子如下:
@Test public void testMapProxy1() { Map<String, Object> userMap = MapUtil.newHashMap(16); userMap.put("username", "alvin"); userMap.put("age", 20); // 使用map的時(shí)候, 需要進(jìn)行強(qiáng)轉(zhuǎn),一旦類(lèi)型錯(cuò)誤,會(huì)報(bào)錯(cuò) String age = (String)userMap.get("age"); }
運(yùn)行結(jié)果:
那有什么更好的解決方案嗎?Hutool提供了一種解決方案給我們。
MapProxy使用
依賴引入
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.8</version> </dependency>
定義一個(gè)可訪問(wèn)接口
interface MapUser { String getUsername(); Integer getAge(); MapUser setAge(Integer age); }
通過(guò)MapProxy訪問(wèn)
@Test public void testMapProxy2() { Map<String, Object> userMap = MapUtil.newHashMap(16); userMap.put("username", "alvin"); userMap.put("age", 20); MapProxy mapProxy = MapProxy.create(userMap); Integer age = mapProxy.getInt("age", 18); Assert.assertTrue(age == 20); // 通過(guò)代理的方式 MapUser mapUser = mapProxy.toProxyBean(MapUser.class); // 后續(xù)訪問(wèn)會(huì)變的更加安全 Assert.assertTrue(mapUser.getAge() == 20); mapUser.setAge(30); Assert.assertTrue(mapUser.getAge() == 30); }
MapProxy源碼解析
Map代理,提供各種getXXX方法,并提供默認(rèn)值支持,它的類(lèi)結(jié)構(gòu)圖如下:
- 實(shí)現(xiàn)了OptNullBasicTypeFromObjectGetter接口, 提供了基本類(lèi)型的get, 在不提供默認(rèn)值的情況下, 如果值不存在或獲取錯(cuò)誤,返回null, 比如:
mapProxy.getInt("age", 18)
。 - 實(shí)現(xiàn)了InvocationHandler接口,支持jdk的動(dòng)態(tài)代理,生成代理對(duì)象。
public <T> T toProxyBean(Class<T> interfaceClass) { return (T) Proxy.newProxyInstance(ClassLoaderUtil.getClassLoader(), new Class<?>[]{interfaceClass}, this); }
- toProxyBean方法就是生成代理對(duì)象,最終會(huì)調(diào)用代理類(lèi)的invoke方法,這里的代理類(lèi)就是MapProxy本身。
public Object invoke(Object proxy, Method method, Object[] args) { final Class<?>[] parameterTypes = method.getParameterTypes(); // 如果調(diào)用方法參數(shù)為空 if (ArrayUtil.isEmpty(parameterTypes)) { final Class<?> returnType = method.getReturnType(); // 方法返回值不是void if (void.class != returnType) { // 匹配Getter final String methodName = method.getName(); String fieldName = null; if (methodName.startsWith("get")) { // 匹配getXXX fieldName = StrUtil.removePreAndLowerFirst(methodName, 3); } else if (BooleanUtil.isBoolean(returnType) && methodName.startsWith("is")) { // 匹配isXXX fieldName = StrUtil.removePreAndLowerFirst(methodName, 2); }else if ("hashCode".equals(methodName)) { return this.hashCode(); } else if ("toString".equals(methodName)) { return this.toString(); } if (StrUtil.isNotBlank(fieldName)) { if (false == this.containsKey(fieldName)) { // 駝峰不存在轉(zhuǎn)下劃線嘗試 fieldName = StrUtil.toUnderlineCase(fieldName); } return Convert.convert(method.getGenericReturnType(), this.get(fieldName)); } } // 如果方法參數(shù)不為空 } else if (1 == parameterTypes.length) { // 匹配Setter final String methodName = method.getName(); if (methodName.startsWith("set")) { final String fieldName = StrUtil.removePreAndLowerFirst(methodName, 3); if (StrUtil.isNotBlank(fieldName)) { this.put(fieldName, args[0]); final Class<?> returnType = method.getReturnType(); // 判斷返回類(lèi)型是不是代理類(lèi)的實(shí)例 if(returnType.isInstance(proxy)){ return proxy; } } } else if ("equals".equals(methodName)) { return this.equals(args[0]); } } throw new UnsupportedOperationException(method.toGenericString()); }
總結(jié)
本文主要講解了Hutool中的MapProxy類(lèi)的使用,希望對(duì)大家有幫助
以上就是Hutool開(kāi)發(fā)利器MapProxy類(lèi)使用技巧詳解的詳細(xì)內(nèi)容,更多關(guān)于Hutool開(kāi)發(fā)MapProxy類(lèi)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用Idea快速搭建SpringMVC項(xiàng)目的詳細(xì)步驟記錄
這篇文章主要給大家介紹了關(guān)于使用Idea快速搭建SpringMVC項(xiàng)目的詳細(xì)步驟,Spring?MVC是一種基于MVC模式的框架,它是Spring框架的一部分,它提供了一種更簡(jiǎn)單和更有效的方式來(lái)構(gòu)建Web應(yīng)用程序,需要的朋友可以參考下2024-05-05SpringMVC使用ResponseEntity實(shí)現(xiàn)文件上傳下載
這篇文章主要為大家介紹了SpringMVC使用ResponseEntity實(shí)現(xiàn)文件上傳下載,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05Windows下使用Graalvm將Springboot應(yīng)用編譯成exe大大提高啟動(dòng)和運(yùn)行效率(推薦)
這篇文章主要介紹了Windows下使用Graalvm將Springboot應(yīng)用編譯成exe大大提高啟動(dòng)和運(yùn)行效率,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-02-02java HashMap,TreeMap與LinkedHashMap的詳解
這篇文章主要介紹了 java HashMap,TreeMap與LinkedHashMap的詳解的相關(guān)資料,這里提供實(shí)例代碼,幫助大家學(xué)習(xí)理解 這部分的內(nèi)容,需要的朋友可以參考下2016-11-11基于Transactional事務(wù)的使用以及注意說(shuō)明
這篇文章主要介紹了Transactional事務(wù)的使用以及注意說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07Spring?Boot日志基礎(chǔ)使用之如何設(shè)置日志級(jí)別
這篇文章主要介紹了Spring?Boot日志基礎(chǔ)使用設(shè)置日志級(jí)別的方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09