xm
2024-06-14 722af26bc6fec32bb289b1df51a9016a4935610f
提交 | 用户 | 时间
722af2 1 package com.dl.common.utils;
X 2
3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.lang.SimpleCache;
5 import cn.hutool.core.map.MapUtil;
6 import cn.hutool.core.util.ObjectUtil;
7 import cn.hutool.core.util.ReflectUtil;
8 import cn.hutool.core.util.StrUtil;
9 import lombok.AccessLevel;
10 import lombok.NoArgsConstructor;
11 import org.springframework.cglib.beans.BeanCopier;
12 import org.springframework.cglib.beans.BeanMap;
13 import org.springframework.cglib.core.Converter;
14
15 import java.util.LinkedHashMap;
16 import java.util.List;
17 import java.util.Map;
18
19 /**
20  * bean深拷贝工具(基于 cglib 性能优异)
21  * <p>
22  * 重点 cglib 不支持 拷贝到链式对象
23  * 例如: 源对象 拷贝到 目标(链式对象)
24  * 请区分好`浅拷贝`和`深拷贝`再做使用
25  *
26  * @author Lion Li
27  */
28 @NoArgsConstructor(access = AccessLevel.PRIVATE)
29 public class BeanCopyUtils {
30
31     /**
32      * 单对象基于class创建拷贝
33      *
34      * @param source 数据来源实体
35      * @param desc   描述对象 转换后的对象
36      * @return desc
37      */
38     public static <T, V> V copy(T source, Class<V> desc) {
39         if (ObjectUtil.isNull(source)) {
40             return null;
41         }
42         if (ObjectUtil.isNull(desc)) {
43             return null;
44         }
45         final V target = ReflectUtil.newInstanceIfPossible(desc);
46         return copy(source, target);
47     }
48
49     /**
50      * 单对象基于对象创建拷贝
51      *
52      * @param source 数据来源实体
53      * @param desc   转换后的对象
54      * @return desc
55      */
56     public static <T, V> V copy(T source, V desc) {
57         if (ObjectUtil.isNull(source)) {
58             return null;
59         }
60         if (ObjectUtil.isNull(desc)) {
61             return null;
62         }
63         BeanCopier beanCopier = BeanCopierCache.INSTANCE.get(source.getClass(), desc.getClass(), null);
64         beanCopier.copy(source, desc, null);
65         return desc;
66     }
67
68     /**
69      * 列表对象基于class创建拷贝
70      *
71      * @param sourceList 数据来源实体列表
72      * @param desc       描述对象 转换后的对象
73      * @return desc
74      */
75     public static <T, V> List<V> copyList(List<T> sourceList, Class<V> desc) {
76         if (ObjectUtil.isNull(sourceList)) {
77             return null;
78         }
79         if (CollUtil.isEmpty(sourceList)) {
80             return CollUtil.newArrayList();
81         }
82         return StreamUtils.toList(sourceList, source -> {
83             V target = ReflectUtil.newInstanceIfPossible(desc);
84             copy(source, target);
85             return target;
86         });
87     }
88
89     /**
90      * bean拷贝到map
91      *
92      * @param bean 数据来源实体
93      * @return map对象
94      */
95     @SuppressWarnings("unchecked")
96     public static <T> Map<String, Object> copyToMap(T bean) {
97         if (ObjectUtil.isNull(bean)) {
98             return null;
99         }
100         return BeanMap.create(bean);
101     }
102
103     /**
104      * map拷贝到bean
105      *
106      * @param map       数据来源
107      * @param beanClass bean类
108      * @return bean对象
109      */
110     public static <T> T mapToBean(Map<String, Object> map, Class<T> beanClass) {
111         if (MapUtil.isEmpty(map)) {
112             return null;
113         }
114         if (ObjectUtil.isNull(beanClass)) {
115             return null;
116         }
117         T bean = ReflectUtil.newInstanceIfPossible(beanClass);
118         return mapToBean(map, bean);
119     }
120
121     /**
122      * map拷贝到bean
123      *
124      * @param map  数据来源
125      * @param bean bean对象
126      * @return bean对象
127      */
128     public static <T> T mapToBean(Map<String, Object> map, T bean) {
129         if (MapUtil.isEmpty(map)) {
130             return null;
131         }
132         if (ObjectUtil.isNull(bean)) {
133             return null;
134         }
135         BeanMap.create(bean).putAll(map);
136         return bean;
137     }
138
139     /**
140      * map拷贝到map
141      *
142      * @param map   数据来源
143      * @param clazz 返回的对象类型
144      * @return map对象
145      */
146     public static <T, V> Map<String, V> mapToMap(Map<String, T> map, Class<V> clazz) {
147         if (MapUtil.isEmpty(map)) {
148             return null;
149         }
150         if (ObjectUtil.isNull(clazz)) {
151             return null;
152         }
153         Map<String, V> copyMap = new LinkedHashMap<>(map.size());
154         map.forEach((k, v) -> copyMap.put(k, copy(v, clazz)));
155         return copyMap;
156     }
157
158     /**
159      * BeanCopier属性缓存<br>
160      * 缓存用于防止多次反射造成的性能问题
161      *
162      * @author Looly
163      * @since 5.4.1
164      */
165     public enum BeanCopierCache {
166         /**
167          * BeanCopier属性缓存单例
168          */
169         INSTANCE;
170
171         private final SimpleCache<String, BeanCopier> cache = new SimpleCache<>();
172
173         /**
174          * 获得类与转换器生成的key在{@link BeanCopier}的Map中对应的元素
175          *
176          * @param srcClass    源Bean的类
177          * @param targetClass 目标Bean的类
178          * @param converter   转换器
179          * @return Map中对应的BeanCopier
180          */
181         public BeanCopier get(Class<?> srcClass, Class<?> targetClass, Converter converter) {
182             final String key = genKey(srcClass, targetClass, converter);
183             return cache.get(key, () -> BeanCopier.create(srcClass, targetClass, converter != null));
184         }
185
186         /**
187          * 获得类与转换器生成的key
188          *
189          * @param srcClass    源Bean的类
190          * @param targetClass 目标Bean的类
191          * @param converter   转换器
192          * @return 属性名和Map映射的key
193          */
194         private String genKey(Class<?> srcClass, Class<?> targetClass, Converter converter) {
195             final StringBuilder key = StrUtil.builder()
196                 .append(srcClass.getName()).append('#').append(targetClass.getName());
197             if (null != converter) {
198                 key.append('#').append(converter.getClass().getName());
199             }
200             return key.toString();
201         }
202     }
203
204 }