Java PO BO DTO VO bean对象互相转换高性能实现工具

news/2024/11/23 9:53:05/

目录

  • 方案一:Cglib BeanCopier
  • 方案二:Spring BeanUtils
  • 方案三:MapStruct
  • 方案四:Orika
  • 方案五:Dozer

方案一:Cglib BeanCopier

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.cglib.beans.BeanMap;import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** 创建对象copy工具类 复制对象采用cglib beanCopier, cglib性能高于spring BeanUtils* 注意:当被复制的实体类使用lombok @Accessors(chain = true)注解时 使用BeanUtil.copy方法失败,请使用 org.springframework.beans.BeanUtils.copyProperties 方法** @author zhaoyang10* @date 2018/10/25*/
@Slf4j
public class BeanUtil {private BeanUtil() {}/*** 缓存copier*/private static final Map<String, BeanCopier> BEAN_COPIERS = new ConcurrentHashMap<>();/*** 对象复制** @param source 源对象-被复制的对象* @param target 目标对象-新对象* @author zhaoyang10*/public static void copy(Object source, Object target) {String beanKey = generateKey(source.getClass(), target.getClass());BeanCopier copier;if (!BEAN_COPIERS.containsKey(beanKey)) {copier = BeanCopier.create(source.getClass(), target.getClass(), false);BEAN_COPIERS.put(beanKey, copier);} else {copier = BEAN_COPIERS.get(beanKey);}copier.copy(source, target, null);}private static String generateKey(Class<?> sourceClass, Class<?> targetClass) {return sourceClass.getName() + ":" + targetClass.getName();}/*** 将对象装换为map*/@SuppressWarnings("unchecked")public static Map<String, Object> beanToMap(Object bean) {return BeanMap.create(bean);}/*** 将map装换为javabean对象*/public static <T> T mapToBean(Map<String, Object> map, T bean) {BeanMap beanMap = BeanMap.create(bean);beanMap.putAll(map);return bean;}/*** 将List<T>转换为List<Map<String, Object>>*/public static <T> List<Map> objectsToMaps(List<T> objList) {List<Map> list = Lists.newArrayList();if (objList != null && !objList.isEmpty()) {Map map;for (Object item : objList) {map = beanToMap(item);list.add(map);}}return list;}/*** 将List<Map<String,Object>>转换为List<T>*/public static <T> List<T> mapsToObjects(List<Map<String, Object>> maps, Class<T> clazz) {try {List<T> list = Lists.newArrayList();if (maps != null && !maps.isEmpty()) {T bean;for (Map<String, Object> item : maps) {bean = clazz.newInstance();mapToBean(item, bean);list.add(bean);}}return list;} catch (Exception e) {log.error("转换出错", e);return Collections.emptyList();}}/*** 通过对象属性名获取对象中的属性值*/public static Object getProp(Object object, String name) {if (object == null || name == null || "".equals(name.trim())) {return null;}try {BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();for (PropertyDescriptor property : propertyDescriptors) {String tempName = property.getName();if (name.equals(tempName)) {Method getter = property.getReadMethod();Object value = null;if (getter != null) {value = getter.invoke(object);}return value;}}} catch (Exception e) {log.error("getProp出错", e);}return null;}}

方案二:Spring BeanUtils

改造BeanUtils优雅实现高频工具类!

方案三:MapStruct

Github 官网

MapStruct使用教程

Java 实体映射工具 MapStruct

方案四:Orika

SpringBoot 如何进行对象复制

OrikaUtils.java 封装工具类

import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import ma.glasnost.orika.metadata.ClassMapBuilder;
import org.springframework.util.CollectionUtils;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** Orika封装的工具类*/
public class OrikaUtils {private static final MapperFactory FACTORY = new DefaultMapperFactory.Builder().build();/*** 缓存实例集合*/private static final Map<String, MapperFacade> CACHE_MAPPER = new ConcurrentHashMap<>();private final MapperFacade mapper;public OrikaUtils(MapperFacade mapper) {this.mapper = mapper;}/*** 转换实体函数* @param sourceEntity 源实体* @param targetClass  目标类对象* @param refMap       配置源类与目标类不同字段名映射* @param <S>          源泛型* @param <T>          目标泛型* @return 目标实体*/public static <S, T> T convert(S sourceEntity, Class<T> targetClass, Map<String, String> refMap) {if (sourceEntity == null) {return null;}return classMap(sourceEntity.getClass(), targetClass, refMap).map(sourceEntity, targetClass);}/*** 转换实体函数** @param sourceEntity 源实体* @param targetClass  目标类对象* @param <S>          源泛型* @param <T>          目标泛型* @return 目标实体*/public static <S, T> T convert(S sourceEntity, Class<T> targetClass) {return convert(sourceEntity, targetClass, null);}/*** 转换实体集合函数** @param sourceEntityList 源实体集合* @param targetClass      目标类对象* @param refMap           配置源类与目标类不同字段名映射* @param <S>              源泛型* @param <T>              目标泛型* @return 目标实体集合*/public static <S, T> List<T> convertList(List<S> sourceEntityList, Class<T> targetClass, Map<String, String> refMap) {if (sourceEntityList == null) {return null;}if (sourceEntityList.size() == 0) {return new ArrayList<>(0);}return classMap(sourceEntityList.get(0).getClass(), targetClass, refMap).mapAsList(sourceEntityList, targetClass);}/*** 转换实体集合函数** @param sourceEntityList 源实体集合* @param targetClass      目标类对象* @param <S>              源泛型* @param <T>              目标泛型* @return 目标实体集合*/public static <S, T> List<T> convertList(List<S> sourceEntityList, Class<T> targetClass) {return convertList(sourceEntityList, targetClass, null);}/*** 注册属性* @param source 源类* @param target 目标类* @param refMap 属性转换*/public static <V, P> void register(Class<V> source, Class<P> target,Map<String, String> refMap){if (CollectionUtils.isEmpty(refMap)) {FACTORY.classMap(source, target).byDefault().register();} else {ClassMapBuilder<V, P> classMapBuilder = FACTORY.classMap(source, target);refMap.forEach(classMapBuilder::field);classMapBuilder.byDefault().register();}}/*** 属性名称一致可用* @param source 源数据* @param target 目标对象* @return OrikaUtils*/private static <V, P> OrikaUtils classMap(Class<V> source, Class<P> target) {return classMap(source, target, null);}/*** 属性名称不一致可用** @param source 原对象* @param target 目标对象* @return OrikaUtils*/private static synchronized <V, P> OrikaUtils classMap(Class<V> source, Class<P> target, Map<String, String> refMap) {String key = source.getCanonicalName() + ":" + target.getCanonicalName();if (CACHE_MAPPER.containsKey(key)) {return new OrikaUtils(CACHE_MAPPER.get(key));}register(source,target,refMap);MapperFacade mapperFacade = FACTORY.getMapperFacade();CACHE_MAPPER.put(key, mapperFacade);return new OrikaUtils(mapperFacade);}/*** Orika复制对象* @param source 源数据* @param target 目标对象* @return target*/private <V, P> P map(V source, Class<P> target) {return mapper.map(source, target);}/*** 复制List* @param source 源对象* @param target 目标对象* @return P*/private <V, P> List<P> mapAsList(List<V> source, Class<P> target) {return CollectionUtils.isEmpty(source) ? Collections.emptyList() : mapper.mapAsList(source, target);}}

方案五:Dozer

Github 官网

Dozer使用教程

Dozer 工具类

import java.util.Collection;
import java.util.List;import org.dozer.DozerBeanMapper;import com.google.common.collect.Lists;/*** 简单封装Dozer, 实现深度转换Bean<->Bean的Mapper.实现:*  * 1. 持有Mapper的单例. * 2. 返回值类型转换.* 3. 批量转换Collection中的所有对象.* 4. 区分创建新的B对象与将对象A值复制到已存在的B对象两种函数.*/
public class BeanMapper {/*** 持有Dozer单例, 避免重复创建DozerMapper消耗资源.*/private static DozerBeanMapper dozer = new DozerBeanMapper();/*** 基于Dozer转换对象的类型.*/public static <T> T map(Object source, Class<T> destinationClass) {return dozer.map(source, destinationClass);}/*** 基于Dozer转换Collection中对象的类型.*/@SuppressWarnings("rawtypes")public static <T> List<T> mapList(Collection sourceList, Class<T> destinationClass) {List<T> destinationList = Lists.newArrayList();for (Object sourceObject : sourceList) {T destinationObject = dozer.map(sourceObject, destinationClass);destinationList.add(destinationObject);}return destinationList;}/*** 基于Dozer将对象A的值拷贝到对象B中.*/public static void copy(Object source, Object destinationObject) {dozer.map(source, destinationObject);}
}

http://www.ppmy.cn/news/804723.html

相关文章

dearmwear和PHP和HtmL_BO-BLOG模板制作指南(上)

一、Bo-blog程序简介 Bo-Blog日志程序(以下简称程序)是由Bob Shen开发的管理员和副管理员共同写作的blog程序&#xff0c;基于PHP脚本和文本数据库。 Bo-blog官方网站&#xff1a;http://www.bo-blog.com Bo-blog官方论坛:http://www.bmforum.com/bmb/forums.php?forumid81 二…

DO、DTO、BO、AO、VO、POJO定义和转换的正确姿势

一、引言 DO、DTO、BO、AO、VO、POJO的概念看似简单&#xff0c;但是想区分好或者理解好也不容易&#xff0c;本文简单梳理一下。 通过各层POJO的使用&#xff0c;有助于提高代码的可读性和可维护性。 -------------------------------------------------------------------…

jetson nano bo1 主板学习配置过程

最近需要在jetson主板上面部署自己的程序&#xff0c;经历了诸多困难以后&#xff0c;终于弄好了&#xff0c;在此记录一下流程以及碰到的问题。预防下次碰到相同的问题。 1.我用的是将系统烧录到sd卡里面的方式。首先找一张内存卡&#xff0c;最好是大点的&#xff0c;我用的…

JAVA怎么设计BO对象_设计概念的统一语言:POJO、BO、VO、DO...

原标题&#xff1a;设计概念的统一语言&#xff1a;POJO、BO、VO、DO... 有必要为领域驱动设计的设计概念定义“统一语言”&#xff0c;通过理解的一致保证交流的畅通&#xff0c;确保架构和设计方案的统一性。。 当我们在讨论领域驱动设计时&#xff0c;不止要谈到领域驱动设计…

RC-u3 跑团机器人(string)

PTA | 程序设计类实验辅助教学平台 #include<bits/stdc.h> using namespace std; const int N1010; int eps; int up,down; int cnt[N]; int main() {string str;cin>>str;str""str"";int num0,s0;int flag0;int op1;for(int i0;i<str.siz…

MIT 6.S081 lab学习记录

lab0 Google 翻译 第零章 操作系统接口 | xv6 中文文档 (gitbooks.io) 6.1810 / Fall 2022 (mit.edu) sleep(easy) #include "kernel/types.h" #include "kernel/stat.h" #include "user/user.h"int main(int argc, char *argv[]){if(argc &l…

如何实现音视频同步 (live555)

live555中视频和音频是分别进行编码的&#xff0c;如何实现两者的同步呢? 如果可以做到让视频和音频的时间戳&#xff0c;都与NTP时间保持同步&#xff0c;就可达到音视频同步的目的。 Network Time Protocol (NTP) is a networking protocol for clock synchronizationbetwee…

音视频的同步原理

1. 音视频同步的原理 2. 音视频同步的较正方法 3. 音视频同步时遇到的问题 声明&#xff1a;以下所有内容均为转载 1.原文转自&#xff1a;http://bbs.chinavideo.org/viewthread.php?tid1183&extrapage%3D1%26amp%3Bfilter%3Ddigest&page1 下面贴出部分&#xff…