提交 | 用户 | 时间
|
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 |
} |