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類型
但是對(duì)于直接生成的beanMap無法添加key,也無法刪除key(會(huì)報(bào)錯(cuò)),并且修改值會(huì)直接影響到student這個(gè)對(duì)象。
如果有這個(gè)需求可以再進(jìn)一步轉(zhuǎn)換為HashMap(如果沒這個(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()方法通過asm動(dòng)態(tài)生成字節(jié)碼創(chuàng)建一個(gè)beanMap
那么我們來看看創(chuàng)建出來的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è)生成的類繼承自BeanMap,在構(gòu)造時(shí)傳進(jìn)來bean實(shí)例,并且根據(jù)bean的屬性創(chuàng)建對(duì)應(yīng)的get/put方法
可以看出來在執(zhí)行g(shù)et和put時(shí)都是根據(jù)屬性名稱找到對(duì)應(yīng)bean實(shí)例的set/get方法進(jìn)行處理。也因此beanMap和對(duì)應(yīng)實(shí)例會(huì)相互影響
還具備getPropertyType獲取字段類型的功能
在bean轉(zhuǎn)map過程中除了生成這個(gè)動(dòng)態(tài)class之外(生成之后會(huì)緩存,對(duì)于同一類型的bean,不會(huì)重復(fù)創(chuàng)建),整個(gè)過程沒有真正復(fù)制對(duì)象變成map(避免的內(nèi)存的浪費(fèi)),也沒有通過效率較慢的反射去操作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)文章
SpringBoot整合Quartz及異步調(diào)用的案例
Quartz是一個(gè)完全由java編寫的開源作業(yè)調(diào)度框架、它的簡(jiǎn)單易用受到業(yè)內(nèi)人士的一致好評(píng),這篇文章主要介紹了SpringBoot整合Quartz及異步調(diào)用,需要的朋友可以參考下2023-03-03
Java的Spring框架中AOP項(xiàng)目的一般配置和部署教程
這篇文章主要介紹了Java的Spring框架中AOP項(xiàng)目的一般配置和部署教程,AOP面向方面編程的項(xiàng)目部署結(jié)構(gòu)都比較類似,因而也被看作是Spring的一種設(shè)計(jì)模式使用,需要的朋友可以參考下2016-04-04
Java中double數(shù)值保留兩位小數(shù)的4種實(shí)現(xiàn)方式舉例
在Java編程中,我們經(jīng)常遇到需要對(duì)double類型的浮點(diǎn)數(shù)進(jìn)行精確截?cái)嗷蛩纳嵛迦氡A魞晌恍?shù)的需求,這篇文章主要給大家介紹了關(guān)于Java中double數(shù)值保留兩位小數(shù)的4種實(shí)現(xiàn)方式,需要的朋友可以參考下2024-07-07
javaweb中mysql數(shù)據(jù)庫(kù)連接步驟方法及其實(shí)例
這篇文章主要介紹了使用java web 連接MySQL數(shù)據(jù)庫(kù)的驅(qū)動(dòng)方法的相關(guān)知識(shí),本文介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-04-04
Java PriorityQueue數(shù)據(jù)結(jié)構(gòu)接口原理及用法
這篇文章主要介紹了Java PriorityQueue數(shù)據(jù)結(jié)構(gòu)接口原理及用法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
Spring線程池ThreadPoolTaskExecutor配置詳情
本篇文章主要介紹了Spring線程池ThreadPoolTaskExecutor配置詳情,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03
Java實(shí)現(xiàn)拓?fù)渑判虻氖纠a
這篇文章我們要講的是拓?fù)渑判颍@是一個(gè)針對(duì)有向無環(huán)圖的算法,主要是為了解決前驅(qū)后繼的關(guān)系,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-05-05

