Java BeanMap實(shí)現(xiàn)Bean與Map的相互轉(zhuǎn)換
net.sf.cglib.beans.BeanMap用法
bean轉(zhuǎn)Map
@Data public class Student { private int id; private String name; private Integer age; }
Student student = new Student(); BeanMap beanMap = BeanMap.create(student);
此時(shí)的beanMap就是一個(gè)map類(lèi)型
但是對(duì)于直接生成的beanMap無(wú)法添加key,也無(wú)法刪除key(會(huì)報(bào)錯(cuò)),并且修改值會(huì)直接影響到student這個(gè)對(duì)象。
如果有這個(gè)需求可以再進(jìn)一步轉(zhuǎn)換為HashMap(如果沒(méi)這個(gè)需要,就不要再轉(zhuǎn)換,避免不必要的性能浪費(fèi))
HashMap map = new HashMap(); map.putAll(beanMap);
map轉(zhuǎn)Bean
普通Map轉(zhuǎn)轉(zhuǎn)換成bean
HashMap map = new HashMap(); map.put("name","hello world"); Student student = new Student(); BeanMap beanMap = BeanMap.create(student); beanMap.putAll(map);
利用了修改beanMap會(huì)影響bean的特性,將map put到beanMap完成轉(zhuǎn)換.
beanMap轉(zhuǎn)成對(duì)應(yīng)的bean
public static <T> T beanMapToBean(BeanMap beanMap) { if (beanMap == null) { throw new DataStreamException("bean.can.not.be.null"); } return (T) beanMap.getBean(); }
直接調(diào)用getBean方法就可以獲取beanMap對(duì)應(yīng)的bean
beanMap實(shí)現(xiàn)以及高性能的原因
先看beanMap
public abstract class BeanMap implements Map
繼承自Map接口,實(shí)現(xiàn)了contains,remove,put,get等操作
public Object remove(Object key) { throw new UnsupportedOperationException(); }
但是remove會(huì)拋出UnsupportedOperationException
BeanMap.create()方法通過(guò)asm動(dòng)態(tài)生成字節(jié)碼創(chuàng)建一個(gè)beanMap
那么我們來(lái)看看創(chuàng)建出來(lái)的beanMap的字節(jié)碼文件
import java.math.BigDecimal; import java.util.Date; import java.util.Set; import net.sf.cglib.beans.BeanMap; import net.sf.cglib.beans.FixedKeySet; public class Student$$BeanMapByCGLIB$$54bf0fe9 extends BeanMap { private static FixedKeySet keys; private static final Class CGLIB$load_class$java$2Eutil$2ESet; private static final Class CGLIB$load_class$java$2Elang$2EInteger; private static final Class CGLIB$load_class$java$2Elang$2EString; private static final Class CGLIB$load_class$java$2Emath$2EBigDecimal; private static final Class CGLIB$load_class$java$2Eutil$2EDate; public Student$$BeanMapByCGLIB$$54bf0fe9() { } public BeanMap newInstance(Object var1) { return new Student$$BeanMapByCGLIB$$54bf0fe9(var1); } public Student$$BeanMapByCGLIB$$54bf0fe9(Object var1) { super(var1); } public Object get(Object var1, Object var2) { Student var10000 = (Student)var1; String var10001 = (String)var2; switch(((String)var2).hashCode()) { case -600094315: if (var10001.equals("friends")) { return var10000.getFriends(); } break; case 3355: if (var10001.equals("id")) { return new Integer(var10000.getId()); } break; case 96511: if (var10001.equals("age")) { return var10000.getAge(); } break; case 3373707: if (var10001.equals("name")) { return var10000.getName(); } break; case 104079552: if (var10001.equals("money")) { return var10000.getMoney(); } break; case 1069376125: if (var10001.equals("birthday")) { return var10000.getBirthday(); } } return null; } public Object put(Object var1, Object var2, Object var3) { Student var10000 = (Student)var1; String var10001 = (String)var2; switch(((String)var2).hashCode()) { case -600094315: if (var10001.equals("friends")) { Set var7 = var10000.getFriends(); var10000.setFriends((Set)var3); return var7; } break; case 3355: if (var10001.equals("id")) { Integer var10003 = new Integer(var10000.getId()); var10000.setId(((Number)var3).intValue()); return var10003; } break; case 96511: if (var10001.equals("age")) { Integer var6 = var10000.getAge(); var10000.setAge((Integer)var3); return var6; } break; case 3373707: if (var10001.equals("name")) { String var5 = var10000.getName(); var10000.setName((String)var3); return var5; } break; case 104079552: if (var10001.equals("money")) { BigDecimal var4 = var10000.getMoney(); var10000.setMoney((BigDecimal)var3); return var4; } break; case 1069376125: if (var10001.equals("birthday")) { Date var10002 = var10000.getBirthday(); var10000.setBirthday((Date)var3); return var10002; } } return null; } static { CGLIB$STATICHOOK1(); keys = new FixedKeySet(new String[]{"birthday", "money", "name", "id", "age", "friends"}); } static void CGLIB$STATICHOOK1() { CGLIB$load_class$java$2Eutil$2ESet = Class.forName("java.util.Set"); CGLIB$load_class$java$2Elang$2EInteger = Class.forName("java.lang.Integer"); CGLIB$load_class$java$2Elang$2EString = Class.forName("java.lang.String"); CGLIB$load_class$java$2Emath$2EBigDecimal = Class.forName("java.math.BigDecimal"); CGLIB$load_class$java$2Eutil$2EDate = Class.forName("java.util.Date"); } public Set keySet() { return keys; } public Class getPropertyType(String var1) { switch(var1.hashCode()) { case -600094315: if (var1.equals("friends")) { return CGLIB$load_class$java$2Eutil$2ESet; } break; case 3355: if (var1.equals("id")) { return Integer.TYPE; } break; case 96511: if (var1.equals("age")) { return CGLIB$load_class$java$2Elang$2EInteger; } break; case 3373707: if (var1.equals("name")) { return CGLIB$load_class$java$2Elang$2EString; } break; case 104079552: if (var1.equals("money")) { return CGLIB$load_class$java$2Emath$2EBigDecimal; } break; case 1069376125: if (var1.equals("birthday")) { return CGLIB$load_class$java$2Eutil$2EDate; } } return null; } }
這個(gè)生成的類(lèi)繼承自BeanMap,在構(gòu)造時(shí)傳進(jìn)來(lái)bean實(shí)例,并且根據(jù)bean的屬性創(chuàng)建對(duì)應(yīng)的get/put方法
可以看出來(lái)在執(zhí)行g(shù)et和put時(shí)都是根據(jù)屬性名稱(chēng)找到對(duì)應(yīng)bean實(shí)例的set/get方法進(jìn)行處理。也因此beanMap和對(duì)應(yīng)實(shí)例會(huì)相互影響
還具備getPropertyType獲取字段類(lèi)型的功能
在bean轉(zhuǎn)map過(guò)程中除了生成這個(gè)動(dòng)態(tài)class之外(生成之后會(huì)緩存,對(duì)于同一類(lèi)型的bean,不會(huì)重復(fù)創(chuàng)建),整個(gè)過(guò)程沒(méi)有真正復(fù)制對(duì)象變成map(避免的內(nèi)存的浪費(fèi)),也沒(méi)有通過(guò)效率較慢的反射去操作bean實(shí)例。因此BeanMap性能是比較不錯(cuò)的
到此這篇關(guān)于Java BeanMap實(shí)現(xiàn)Bean與Map的相互轉(zhuǎn)換的文章就介紹到這了,更多相關(guān)Bean與Map的相互轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javaweb 實(shí)現(xiàn)文件下載的方法及實(shí)例代碼
這篇文章主要介紹了javaweb 實(shí)現(xiàn)文件下載的方法的相關(guān)資料,這里提供了實(shí)現(xiàn)代碼,需要的朋友可以參考下2016-11-11Spring?Boot集成JavaMailSender發(fā)送郵件功能的實(shí)現(xiàn)
spring提供了發(fā)送郵件的接口JavaMailSender,通過(guò)JavaMailSender可以實(shí)現(xiàn)后端發(fā)送郵件,下面這篇文章主要給大家介紹了關(guān)于Spring?Boot集成JavaMailSender發(fā)送郵件功能的相關(guān)資料,需要的朋友可以參考下2022-05-05springboot使用shiro-整合redis作為緩存的操作
這篇文章主要介紹了springboot使用shiro-整合redis作為緩存的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06m1 Mac設(shè)置多jdk版本并動(dòng)態(tài)切換的實(shí)現(xiàn)
本文主要介紹 Mac 下如何安裝 JDK 并且多版本如何切換,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08