1 package com.zhouyy.netBank.util;
2
3 import java.beans.PropertyDescriptor;
4 import java.lang.reflect.Field;
5 import java.lang.reflect.Method;
6 import java.lang.reflect.Modifier;
7 import java.util.ArrayList;
8 import java.util.Arrays;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.concurrent.ConcurrentHashMap;
13
14 import org.springframework.beans.BeansException;
15 import org.springframework.beans.FatalBeanException;
16 import org.springframework.util.Assert;
17 import org.springframework.util.ClassUtils;
18 import org.springframework.util.CollectionUtils;
19
20 import com.zhouyy.netBank.framework.cglib.beans.BeanCopier;
21 import com.zhouyy.netBank.framework.cglib.beans.BeanMap;
22
23 /**
24 * Bean转换工具
25 *
26 * @author zhouyy
27 * @version 0.0.5
28 */
29 public abstract class BeanUtils extends org.springframework.beans.BeanUtils {
30
31 private static final Map BEAN_COPIER_MAP = new ConcurrentHashMap<>();
32 private static final Map NONE_NULL_BEAN_COPIER_MAP = new ConcurrentHashMap<>();
33
34 /**
35 * MAP集合转成bean对象集合
36 *
37 * @param listResult 需要拷贝的集合
38 * @param clazz 需要将map转换成的Class
39 * @param 泛型
40 * @return 集合泛型
41 * @author zhouyy
42 */
43 public static List copyMapListProperties(List listResult, Class clazz) {
44 List sourceList = new ArrayList<>();
45 Map cacheMap = new HashMap<>();
46 // 遍历MAP结果集
47 for (Object obj : listResult) {
48 Map map = (Map) obj;
49 B source = copyMapProperties(map, clazz, cacheMap);
50 // if (null != clazz) {
51 // source = copyMapProperties(map, clazz, cacheMap);
52 // } else {
53 // Map newMap = new HashMap<>();
54 // Iterator> entries = map.entrySet().iterator();
55 // while (entries.hasNext()) {
56 // Map.Entry entry = entries.next();
57 // newMap.put(entry.getKey().toLowerCase(), entry.getValue());
58 // }
59 // source = (B) newMap;
60 // }
61 sourceList.add(source);
62 }
63 return sourceList;
64 }
65
66 /**
67 * MAP转成bean对象集合
68 *
69 * @param map
70 * @param clazz
71 * @param
72 * @return
73 * @author zhouyy
74 */
75 public static B copyMapProperties(Map map, Class clazz) {
76 Map cacheMap = new HashMap<>();
77 return copyMapProperties(map, clazz, cacheMap);
78 }
79
80 /**
81 * 递归获取当前class的所有父类中的属性
82 *
83 * @param clazz 需要获取的类
84 * @param fieldList 字段集合
85 */
86 public static void getAllFields(Class<?> clazz, List fieldList) {
87 Class superClass = clazz.getSuperclass();
88 if (superClass != Object.class ) {
89 getAllFields(superClass, fieldList);
90 }
91 Field[] fields = clazz.getDeclaredFields();
92 fieldList.addAll(Arrays.asList(fields));
93 }
94
95 /**
96 * MAP转成bean对象集合
97 *
98 * @param map
99 * @param clazz
100 * @param cacheMap
101 * @param
102 * @return
103 * @author zhouyy
104 */
105 @SuppressWarnings("unchecked")
106 private static B copyMapProperties(Map map, Class clazz, Map cacheMap) {
107 Assert.notNull(map, "map must not be null");
108 Assert.notNull(clazz, "clazz must not be null");
109
110 B instantiate = instantiate(clazz);
111 BeanMap beanMap = BeanMap.create(instantiate, true );
112 beanMap.putAll(map);
113 return instantiate;
114
115 // List fieldList = (List) cacheMap.get(clazz);
116 // if (fieldList == null) {
117 // fieldList = new ArrayList<>();
118 // getAllFields(clazz, fieldList);
119 // }
120 //
121 // B source = null;
122 // try {
123 // source = clazz.newInstance();
124 // } catch (InstantiationException | IllegalAccessException e) {
125 // e.printStackTrace();
126 // }
127 // // 遍历结果MAP
128 // Iterator> it = map.entrySet().iterator();
129 // while (it.hasNext()) {
130 // Map.Entry entry = it.next();
131 // // 遍历映射实体属性
132 // for (Field field : fieldList) {
133 // String key = entry.getKey();
134 // Boolean flag = (Boolean) cacheMap.get(key + field.getName());
135 // if (flag == null) {
136 // flag = !key.replace("_", "").equalsIgnoreCase(field.getName());
137 // cacheMap.put(key + field.getName(), flag);
138 // }
139 // if (flag) {
140 // continue;
141 // }
142 //
143 // Object value = entry.getValue();
144 // Class typeClass = field.getType();
145 // Object valueType = setFieldValueByFieldType(value, typeClass);
146 // ReflectionUtils.makeAccessible(field);
147 // ReflectionUtils.setField(field, source, valueType);
148 // }
149 // }
150 // return source;
151 }
152
153 // private static Object setFieldValueByFieldType(Object value, Class typeClass) {
154 // // 这里去掉typeClass == double.class是为了代码规范,保证bean中的属性使用包装类
155 // if ((value instanceof Character) && typeClass == String.class) {
156 // Character character = (Character) value;
157 // value = character.toString();
158 // }else if(value instanceof Number){
159 // Number number = (Number) value;
160 // if (typeClass == BigDecimal.class) {
161 // value = BigDecimal.valueOf(number.doubleValue());
162 // } else if (typeClass == BigInteger.class) {
163 // value = BigInteger.valueOf(number.longValue());
164 // } else if (typeClass == Long.class) {
165 // value = number.longValue();
166 // } else if (typeClass == Integer.class) {
167 // value = number.intValue();
168 // } else if (typeClass == Double.class) {
169 // value = number.doubleValue();
170 // } else if (typeClass == Float.class) {
171 // value = number.floatValue();
172 // } else if (typeClass == Short.class) {
173 // value = number.shortValue();
174 // } else if (typeClass == Byte.class) {
175 // value = number.byteValue();
176 // } else {
177 // value = number;
178 // }
179 // }
180 // return value;
181 // }
182 private static String getBeanCopierCacheKey(Class source, Class target) {
183 return source.getName() + "|" + target.getName();
184 }
185
186 private static BeanCopier getBeanCopier(Class source, Class target) {
187 String beanCopierCacheKey = getBeanCopierCacheKey(source, target);
188 BeanCopier beanCopier = BEAN_COPIER_MAP.get(beanCopierCacheKey);
189 if (beanCopier == null ) {
190 beanCopier = BeanCopier.create(source, target, false );
191 BEAN_COPIER_MAP.put(beanCopierCacheKey, beanCopier);
192 }
193 return beanCopier;
194 }
195
196 private static BeanCopier getNoneNullBeanCopier(Class source, Class target) {
197 String beanCopierCacheKey = getBeanCopierCacheKey(source, target);
198 BeanCopier beanCopier = NONE_NULL_BEAN_COPIER_MAP.get(getBeanCopierCacheKey(source, target));
199 if (beanCopier == null ) {
200 beanCopier = BeanCopier.create(source, target, false , true );
201 NONE_NULL_BEAN_COPIER_MAP.put(beanCopierCacheKey, beanCopier);
202 }
203 return beanCopier;
204 }
205
206 /**
207 * 作者:zhouyy
208 * 批量转换List
209 *
210 * @param source list集合
211 * @param t 所成对象的class
212 * @param
213 * @return List
214 * @throws BeansException
215 */
216 public static List copyListProperties(List source, Class t) throws BeansException {
217 List list = new ArrayList<>();
218 if (CollectionUtils.isEmpty(source)) {
219 return list;
220 }
221
222 BeanCopier beanCopier = getBeanCopier(source.get(0).getClass(), t);
223 for (Object o : source) {
224 B instantiate = instantiate(t);
225 beanCopier.copy(o, instantiate, null );
226 // copyProperties(o, instantiate);
227 list.add(instantiate);
228 }
229 return list;
230 // List list = new ArrayList<>();
231 // if (source == null) {
232 // return list;
233 // }
234 // try {
235 // for (Object o : source) {
236 // B tObj = t.newInstance();
237 // copyProperties(o, tObj);
238 // list.add(tObj);
239 // }
240 // } catch (InstantiationException | IllegalAccessException e) {
241 // e.printStackTrace();
242 // }
243 // return list;
244 }
245
246
247 public static Map beanToMap(Object obj) {
248 BeanMap beanMap = BeanMap.create(obj);
249 HashMap copy = new HashMap<>();
250 for (Object key : beanMap.keySet()) {
251 copy.put((String) key, beanMap.get(key));
252 }
253 return copy;
254 // if (obj == null) {
255 // return null;
256 // }
257 // Map map = new HashMap<>();
258 // try {
259 // BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
260 // PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
261 // for (PropertyDescriptor property : propertyDescriptors) {
262 // String key = property.getName();
263 // // 过滤class属性
264 // if (!key.equals("class")) {
265 // // 得到property对应的getter方法
266 // Method getter = property.getReadMethod();
267 // Object value = getter.invoke(obj);
268 //
269 // map.put(key, value);
270 // }
271 // }
272 // } catch (Exception e) {
273 // logger.error("transBean2Map Error {}", e);
274 // }
275 // return map;
276 }
277
278 /**
279 * 将两个对象集合合并,并且转换为Map集合
280 *
281 * @param listA 对象集合A
282 * @param listB 对象集合B
283 * @param key 根据对象中的哪个值进行合并
284 * @return 合并后的Map集合
285 */
286 public static List> mergeListBeanToMap(List<?> listA, List<?> listB, String key) {
287 List> list = new ArrayList<>();
288 for (Object objA : listA) {
289 // 将对象转换为Map
290 Map mapA = beanToMap(objA);
291 for (Object objB : listB) {
292 // 将对象转换为Map
293 Map mapB = beanToMap(objB);
294 // 如果对象A和对象B的值一直,则合并两个对象Map
295 if (mapA.get(key).equals(mapB.get(key))) {
296 mapA.putAll(mapB);
297 }
298 }
299 // 如果集合中不存在Map,则往List中追加合并后的Map
300 if (!list.contains(mapA)) {
301 list.add(mapA);
302 }
303 }
304 return list;
305 }
306
307 /**
308 * 将两个对象转换为map并做合并操作
309 *
310 * @param objA 对象A
311 * @param objB 对象B
312 * @param key 根据什么属性合并,属性名
313 * @return 合并后的Map
314 */
315 public static Map mergeBeanToMap(Object objA, Object objB, String key) {
316 if (objA == null ) {
317 return null ;
318 }
319 Map mapA = beanToMap(objA);
320 if (objB == null ) {
321 return mapA;
322 }
323 Map mapB = beanToMap(objB);
324 if (mapA.get(key).equals(mapB.get(key))) {
325 mapA.putAll(mapB);
326 }
327 return mapA;
328 }
329
330 /**
331 * 把source和target相同属性的value复制到target中
332 *
333 * @param source 准备赋值对象
334 * @param target 被赋值对象
335 * @throws BeansException
336 */
337 public static void copyNotNullProperties(Object source, Object target) throws BeansException {
338 BeanCopier noneNullBeanCopier = getNoneNullBeanCopier(source.getClass(), target.getClass());
339 noneNullBeanCopier.copy(source, target, null );
340 // copyProperties(source, target, null, null);
341 }
342
343 public static void copyNotNullProperties(Object source, Object target, String... ignoreProperties) throws BeansException {
344 copyProperties(source, target, null , ignoreProperties);
345 }
346
347 public static B copyNewInstanceProperties(Object source, Class t) throws BeansException {
348 BeanCopier beanCopier = getBeanCopier(source.getClass(), t);
349 B instantiate = instantiate(t);
350 beanCopier.copy(source, instantiate, null );
351 return instantiate;
352 // B tObj = null;
353 // try {
354 // tObj = t.newInstance();
355 // } catch (InstantiationException | IllegalAccessException e) {
356 // logger.error("copyNewInstanceProperties Error {}", e);
357 // }
358 // copyProperties(source, tObj);
359 // return tObj;
360 }
361
362 private static void copyProperties(Object source, Object target, Class<?> editable, String... ignoreProperties) throws BeansException {
363
364 Assert.notNull(source, "Source must not be null");
365 Assert.notNull(target, "Target must not be null");
366
367 Class<?> actualEditable = target.getClass();
368 if (editable != null ) {
369 if (!editable.isInstance(target)) {
370 throw new IllegalArgumentException("Target class [" + target.getClass().getName() +
371 "] not assignable to Editable class [" + editable.getName() + "]");
372 }
373 actualEditable = editable;
374 }
375 PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
376 List ignoreList = (ignoreProperties != null ) ? Arrays.asList(ignoreProperties) : null ;
377
378 for (PropertyDescriptor targetPd : targetPds) {
379 Method writeMethod = targetPd.getWriteMethod();
380 if (writeMethod != null && (ignoreProperties == null || (!ignoreList.contains(targetPd.getName())))) {
381 PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
382 if (sourcePd != null ) {
383 Method readMethod = sourcePd.getReadMethod();
384 if (readMethod != null &&
385 ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
386 try {
387 if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
388 readMethod.setAccessible(true );
389 }
390 Object value = readMethod.invoke(source);
391 if (value != null ) { // 只拷贝不为null的属性
392 if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
393 writeMethod.setAccessible(true );
394 }
395 writeMethod.invoke(target, value);
396 }
397 } catch (Throwable ex) {
398 throw new FatalBeanException(
399 "Could not copy property '" + targetPd.getName() + "' from source to target", ex);
400 }
401 }
402 }
403 }
404 }
405 }
406 }
1 //
2 // Source code recreated from a .class file by IntelliJ IDEA
3 // (powered by Fernflower decompiler)
4 //
5
6 package com.zhouyy.netBank.framework.cglib.beans;
7
8 import org.springframework.asm.ClassVisitor;
9 import org.springframework.asm.Label;
10 import org.springframework.asm.Type;
11 import org.springframework.cglib.core.*;
12
13 import java.beans.PropertyDescriptor;
14 import java.lang.reflect.Modifier;
15 import java.security.ProtectionDomain;
16 import java.util.HashMap;
17 import java.util.Map;
18
19 public abstract class BeanCopier {
20 private static final BeanCopier.BeanCopierKey KEY_FACTORY = (BeanCopier.BeanCopierKey) KeyFactory.create(BeanCopier.BeanCopierKey.class );
21 private static final Type CONVERTER = TypeUtils.parseType("org.springframework.cglib.core.Converter");
22 private static final Type BEAN_COPIER = TypeUtils.parseType(BeanCopier.class .getName());
23 private static final Signature COPY;
24 private static final Signature CONVERT;
25
26 public BeanCopier() {
27 }
28
29 public static BeanCopier create(Class source, Class target, boolean useConverter) {
30 BeanCopier.Generator gen = new BeanCopier.Generator();
31 gen.setSource(source);
32 gen.setTarget(target);
33 gen.setUseConverter(useConverter);
34 return gen.create();
35 }
36
37 public static BeanCopier create(Class source, Class target, boolean useConverter, boolean useNoneNull) {
38 BeanCopier.Generator gen = new BeanCopier.Generator();
39 gen.setSource(source);
40 gen.setTarget(target);
41 gen.setUseConverter(useConverter);
42 gen.setUseNoneNull(useNoneNull);
43 return gen.create();
44 }
45
46 public abstract void copy(Object var1, Object var2, Converter var3);
47
48 static {
49 COPY = new Signature("copy", Type.VOID_TYPE, new Type[]{Constants.TYPE_OBJECT, Constants.TYPE_OBJECT, CONVERTER});
50 CONVERT = TypeUtils.parseSignature("Object convert(Object, Class, Object)");
51 }
52
53 public static class Generator extends AbstractClassGenerator {
54 private static final Source SOURCE = new Source(BeanCopier.class .getName());
55 private Class source;
56 private Class target;
57 // 使用转换器
58 private boolean useConverter;
59 // 使用非空判断
60 private boolean useNoneNull;
61
62 public Generator() {
63 super (SOURCE);
64 }
65
66 public void setSource(Class source) {
67 if (!Modifier.isPublic(source.getModifiers())) {
68 this .setNamePrefix(source.getName());
69 }
70
71 this .source = source;
72 }
73
74 public void setTarget(Class target) {
75 if (!Modifier.isPublic(target.getModifiers())) {
76 this .setNamePrefix(target.getName());
77 }
78
79 this .target = target;
80 }
81
82
83 public void setUseNoneNull(boolean useNoneNull) {
84 this .useNoneNull = useNoneNull;
85 }
86
87 public void setUseConverter(boolean useConverter) {
88 this .useConverter = useConverter;
89 }
90
91 protected ClassLoader getDefaultClassLoader() {
92 return this .source.getClassLoader();
93 }
94
95 protected ProtectionDomain getProtectionDomain() {
96 return ReflectUtils.getProtectionDomain(this .source);
97 }
98
99 public BeanCopier create() {
100 Object key = KEY_FACTORY.newInstance(source.getName(), target.getName(), useConverter,this .useNoneNull);
101 return (BeanCopier)super .create(key);
102 }
103
104 public void generateClass(ClassVisitor v) {
105 Type sourceType = Type.getType(source);
106 Type targetType = Type.getType(target);
107 ClassEmitter ce = new ClassEmitter(v);
108 ce.begin_class(Constants.V1_7, Constants.ACC_PUBLIC, getClassName(), BEAN_COPIER, null , Constants.SOURCE_FILE);
109
110 EmitUtils.null_constructor(ce);
111 CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, COPY, null );
112 PropertyDescriptor[] getters = ReflectUtils.getBeanGetters(source);
113 PropertyDescriptor[] setters = ReflectUtils.getBeanSetters(target);
114 Map names = new HashMap<>();
115
116 for (int i = 0; i < getters.length; ++i) {
117 names.put(getters[i].getName(), getters[i]);
118 }
119
120 Local targetLocal = e.make_local();
121 Local sourceLocal = e.make_local();
122 if (this .useConverter) {
123 e.load_arg(1);
124 e.checkcast(targetType);
125 e.store_local(targetLocal);
126 e.load_arg(0);
127 e.checkcast(sourceType);
128 e.store_local(sourceLocal);
129 } else {
130 e.load_arg(1);
131 e.checkcast(targetType);
132 e.load_arg(0);
133 e.checkcast(sourceType);
134 }
135
136 for (int i = 0; i < setters.length; ++i) {
137 PropertyDescriptor setter = setters[i];
138 PropertyDescriptor getter = (PropertyDescriptor) names.get(setter.getName());
139 if (getter != null ) {
140 Class<?> returnType = getter.getReadMethod().getReturnType();
141 // 是否为基本数据类型 true是,false否
142 boolean isPrimitive = returnType.isPrimitive();
143 MethodInfo read = ReflectUtils.getMethodInfo(getter.getReadMethod());
144 MethodInfo write = ReflectUtils.getMethodInfo(setter.getWriteMethod());
145 Type setterType = write.getSignature().getArgumentTypes()[0];
146 if (this .useConverter) {
147 Label start = null ;
148 if (this .useNoneNull && !isPrimitive) {
149 // 将sourceLocal压入栈顶,以便在if处能获取到source对象的变量
150 e.load_local(sourceLocal);
151 // 创建标签
152 start = e.make_label();
153 // 调用getter方法,获取值
154 e.invoke(read);
155 // 进行非空判断
156 e.ifnull(start);
157 }
158 e.load_local(targetLocal);
159 e.load_arg(2);
160 e.load_local(sourceLocal);
161 e.invoke(read);
162 e.box(read.getSignature().getReturnType());
163 EmitUtils.load_class(e, setterType);
164 e.push(write.getSignature().getName());
165 e.invoke_interface(BeanCopier.CONVERTER, BeanCopier.CONVERT);
166 e.unbox_or_zero(setterType);
167 e.invoke(write);
168
169 if (start != null ) {
170 // 结束
171 e.mark(start);
172 }
173 } else if (compatible(getter, setter)) {
174 // 如果是非空复制
175 Label start = null ;
176 if (this .useNoneNull && !isPrimitive) {
177 // 复制栈顶并进行压栈
178 e.dup();
179 // 创建标签
180 start = e.make_label();
181 // 调用getter方法,获取值
182 e.invoke(read);
183 // 进行非空判断
184 e.ifnull(start);
185 }
186 e.dup2();
187 e.invoke(read);
188 e.invoke(write);
189 if (start != null ) {
190 // 结束
191 e.mark(start);
192 }
193 }
194 }
195 }
196 e.return_value();
197 e.end_method();
198 ce.end_class();
199 }
200
201 private static boolean compatible(PropertyDescriptor getter, PropertyDescriptor setter) {
202 return setter.getPropertyType().isAssignableFrom(getter.getPropertyType());
203 }
204
205 protected Object firstInstance(Class type) {
206 return ReflectUtils.newInstance(type);
207 }
208
209 protected Object nextInstance(Object instance) {
210 return instance;
211 }
212 }
213
214 interface BeanCopierKey {
215 Object newInstance(String var1, String var2, boolean var3, boolean useNoneNull);
216 }
217 }
1 package com.zhouyy.netBank.framework.cglib.beans;
2
3 import java.math.BigDecimal;
4 import java.math.BigInteger;
5
6 /**
7 * 基础数据类型转换,在BeanMapEmitter使用cglib生成的代码中使用该类
8 *
9 * @author zhoul
10 * create time 2019-06-20
11 */
12 public abstract class BasicDataCast {
13
14 public static Object cast(Object source, Class target) {
15 if (source == null ){
16 return null ;
17 }
18 // 如果类型一致,则直接返回
19 if (source.getClass() == target) {
20 return source;
21 }
22 if (source instanceof Character) {
23 Character character = (Character) source;
24 if (target == String.class ) {
25 return character.toString();
26 }
27 } else if (source instanceof CharSequence) {
28 CharSequence character = (CharSequence) source;
29 if (target == String.class ) {
30 return character.toString();
31 }
32 } else if (source instanceof Number) {
33 Number number = (Number) source;
34 if (target == BigDecimal.class ) {
35 return BigDecimal.valueOf(number.doubleValue());
36 } else if (target == BigInteger.class ) {
37 return BigInteger.valueOf(number.longValue());
38 } else if (target == Long.class ) {
39 return number.longValue();
40 } else if (target == Integer.class ) {
41 return number.intValue();
42 } else if (target == Double.class ) {
43 return number.doubleValue();
44 } else if (target == Float.class ) {
45 return number.floatValue();
46 } else if (target == Short.class ) {
47 return number.shortValue();
48 } else if (target == Byte.class ) {
49 return number.byteValue();
50 }else if (target == String.class ) {
51 return number.toString();
52 }
53 }
54 return source;
55 }
56 }
1 package com.zhouyy.netBank.framework.cglib.beans;
2
3 import org.springframework.asm.ClassVisitor;
4 import org.springframework.cglib.core.AbstractClassGenerator;
5 import org.springframework.cglib.core.KeyFactory;
6 import org.springframework.cglib.core.ReflectUtils;
7
8 import java.security.ProtectionDomain;
9 import java.util.*;
10
11 /**
12 * A Map
-based view of a JavaBean. The default set of keys is the
13 * union of all property names (getters or setters). An attempt to set
14 * a read-only property will be ignored, and write-only properties will
15 * be returned as null
. Removal of objects is not a
16 * supported (the key set is fixed).
17 *
18 * @author Chris Nokleberg
19 * @author zhoul
20 */
21 abstract public class BeanMap implements Map {
22 /**
23 * Limit the properties reflected in the key set of the map
24 * to readable properties.
25 *
26 * @see BeanMap.Generator#setRequire
27 */
28 public static final int REQUIRE_GETTER = 1;
29
30 /**
31 * Limit the properties reflected in the key set of the map
32 * to writable properties.
33 *
34 * @see BeanMap.Generator#setRequire
35 */
36 public static final int REQUIRE_SETTER = 2;
37
38 /**
39 * Helper method to create a new BeanMap
. For finer
40 * control over the generated instance, use a new instance of
41 * BeanMap.Generator
instead of this static method.
42 *
43 * @param bean the JavaBean underlying the map
44 * @return a new BeanMap
instance
45 */
46 public static BeanMap create(Object bean) {
47 Generator gen = new Generator();
48 gen.setBean(bean);
49 return gen.create();
50 }
51
52 /**
53 * 创建对象
54 *
55 * @param bean
56 * @param ignoreKeyCase 是否忽略KEY的大小写,要与putAllIgnoreKeyCase配合使用
57 * @return
58 */
59 public static BeanMap create(Object bean, boolean ignoreKeyCase) {
60 Generator gen = new Generator();
61 gen.setBean(bean);
62 gen.setIgnoreKeyCase(ignoreKeyCase);
63 return gen.create();
64 }
65
66 public static class Generator extends AbstractClassGenerator {
67 private static final Source SOURCE = new Source(BeanMap.class .getName());
68
69 private static final BeanMapKey KEY_FACTORY =
70 (BeanMapKey) KeyFactory.create(BeanMapKey.class , KeyFactory.CLASS_BY_NAME);
71
72 interface BeanMapKey {
73 public Object newInstance(Class type, int require, boolean ignoreKeyCase);
74 }
75
76 private Object bean;
77 private Class beanClass;
78 private int require;
79 private boolean ignoreKeyCase;
80
81 public Generator() {
82 super (SOURCE);
83 }
84
85 public void setIgnoreKeyCase(boolean ignoreKeyCase) {
86 this .ignoreKeyCase = ignoreKeyCase;
87 }
88
89 /**
90 * Set the bean that the generated map should reflect. The bean may be swapped
91 * out for another bean of the same type using { @link #setBean}.
92 * Calling this method overrides any value previously set using { @link #setBeanClass}.
93 * You must call either this method or { @link #setBeanClass} before { @link #create}.
94 *
95 * @param bean the initial bean
96 */
97 public void setBean(Object bean) {
98 this .bean = bean;
99 if (bean != null )
100 beanClass = bean.getClass();
101 }
102
103 /**
104 * Set the class of the bean that the generated map should support.
105 * You must call either this method or { @link #setBeanClass} before { @link #create}.
106 *
107 * @param beanClass the class of the bean
108 */
109 public void setBeanClass(Class beanClass) {
110 this .beanClass = beanClass;
111 }
112
113 /**
114 * Limit the properties reflected by the generated map.
115 *
116 * @param require any combination of { @link #REQUIRE_GETTER} and
117 * { @link #REQUIRE_SETTER}; default is zero (any property allowed)
118 */
119 public void setRequire(int require) {
120 this .require = require;
121 }
122
123 protected ClassLoader getDefaultClassLoader() {
124 return beanClass.getClassLoader();
125 }
126
127 protected ProtectionDomain getProtectionDomain() {
128 return ReflectUtils.getProtectionDomain(beanClass);
129 }
130
131 /**
132 * Create a new instance of the BeanMap
. An existing
133 * generated class will be reused if possible.
134 */
135 public BeanMap create() {
136 if (beanClass == null ) {
137 throw new IllegalArgumentException("Class of bean unknown");
138 }
139 setNamePrefix(beanClass.getName());
140 return (BeanMap) super .create(KEY_FACTORY.newInstance(beanClass, require, ignoreKeyCase));
141 }
142
143 public void generateClass(ClassVisitor v) throws Exception {
144 new BeanMapEmitter(v, getClassName(), beanClass, require, ignoreKeyCase);
145 }
146
147 protected Object firstInstance(Class type) {
148 return ((BeanMap) ReflectUtils.newInstance(type)).newInstance(bean);
149 }
150
151 protected Object nextInstance(Object instance) {
152 return ((BeanMap) instance).newInstance(bean);
153 }
154 }
155
156 /**
157 * Create a new BeanMap
instance using the specified bean.
158 * This is faster than using the { @link #create} static method.
159 *
160 * @param bean the JavaBean underlying the map
161 * @return a new BeanMap
instance
162 */
163 abstract public BeanMap newInstance(Object bean);
164
165 /**
166 * Get the type of a property.
167 *
168 * @param name the name of the JavaBean property
169 * @return the type of the property, or null if the property does not exist
170 */
171 abstract public Class getPropertyType(String name);
172
173 protected Object bean;
174
175 protected BeanMap() {
176 }
177
178 protected BeanMap(Object bean) {
179 setBean(bean);
180 }
181
182 public Object get(Object key) {
183 return get(bean, key);
184 }
185
186 public Object put(Object key, Object value) {
187 return put(bean, key, value);
188 }
189
190 /**
191 * Get the property of a bean. This allows a BeanMap
192 * to be used statically for multiple beans--the bean instance tied to the
193 * map is ignored and the bean passed to this method is used instead.
194 *
195 * @param bean the bean to query; must be compatible with the type of
196 * this BeanMap
197 * @param key must be a String
198 * @return the current value, or null if there is no matching property
199 */
200 abstract public Object get(Object bean, Object key);
201
202 /**
203 * Set the property of a bean. This allows a BeanMap
204 * to be used statically for multiple beans--the bean instance tied to the
205 * map is ignored and the bean passed to this method is used instead.
206 *
207 * @param key must be a String
208 * @return the old value, if there was one, or null
209 */
210 abstract public Object put(Object bean, Object key, Object value);
211
212 /**
213 * Change the underlying bean this map should use.
214 *
215 * @param bean the new JavaBean
216 * @see #getBean
217 */
218 public void setBean(Object bean) {
219 this .bean = bean;
220 }
221
222 /**
223 * Return the bean currently in use by this map.
224 *
225 * @return the current JavaBean
226 * @see #setBean
227 */
228 public Object getBean() {
229 return bean;
230 }
231
232 public void clear() {
233 throw new UnsupportedOperationException();
234 }
235
236 public boolean containsKey(Object key) {
237 return keySet().contains(key);
238 }
239
240 public boolean containsValue(Object value) {
241 for (Iterator it = keySet().iterator(); it.hasNext(); ) {
242 Object v = get(it.next());
243 if (((value == null ) && (v == null )) || (value != null && value.equals(v)))
244 return true ;
245 }
246 return false ;
247 }
248
249 public int size() {
250 return keySet().size();
251 }
252
253 public boolean isEmpty() {
254 return size() == 0;
255 }
256
257 public Object remove(Object key) {
258 throw new UnsupportedOperationException();
259 }
260
261 public void putAll(Map t) {
262 for (Iterator it = t.keySet().iterator(); it.hasNext(); ) {
263 Object key = it.next();
264 put(key, t.get(key));
265 }
266 }
267
268 public boolean equals(Object o) {
269 if (o == null || !(o instanceof Map)) {
270 return false ;
271 }
272 Map other = (Map) o;
273 if (size() != other.size()) {
274 return false ;
275 }
276 for (Iterator it = keySet().iterator(); it.hasNext(); ) {
277 Object key = it.next();
278 if (!other.containsKey(key)) {
279 return false ;
280 }
281 Object v1 = get(key);
282 Object v2 = other.get(key);
283 if (!((v1 == null ) ? v2 == null : v1.equals(v2))) {
284 return false ;
285 }
286 }
287 return true ;
288 }
289
290 public int hashCode() {
291 int code = 0;
292 for (Iterator it = keySet().iterator(); it.hasNext(); ) {
293 Object key = it.next();
294 Object value = get(key);
295 code += ((key == null ) ? 0 : key.hashCode()) ^
296 ((value == null ) ? 0 : value.hashCode());
297 }
298 return code;
299 }
300
301 // TODO: optimize
302 public Set entrySet() {
303 HashMap copy = new HashMap<>();
304 for (Object key : keySet()) {
305 copy.put(key, get(key));
306 }
307 return Collections.unmodifiableMap(copy).entrySet();
308 }
309
310 public Collection values() {
311 Set keys = keySet();
312 List values = new ArrayList<>(keys.size());
313 for (Object key : keys) {
314 values.add(get(key));
315 }
316 return Collections.unmodifiableCollection(values);
317 }
318
319 /*
320 * @see java.util.AbstractMap#toString
321 */
322 public String toString() {
323 StringBuffer sb = new StringBuffer();
324 sb.append('{');
325 for (Iterator it = keySet().iterator(); it.hasNext(); ) {
326 Object key = it.next();
327 sb.append(key);
328 sb.append('=');
329 sb.append(get(key));
330 if (it.hasNext()) {
331 sb.append(", ");
332 }
333 }
334 sb.append('}');
335 return sb.toString();
336 }
337 }
1 package com.zhouyy.netBank.framework.cglib.beans;
2
3 import org.springframework.asm.ClassVisitor;
4 import org.springframework.asm.Label;
5 import org.springframework.asm.Type;
6 import org.springframework.cglib.beans.FixedKeySet;
7 import org.springframework.cglib.core.*;
8 import org.springframework.util.StringUtils;
9
10 import java.beans.PropertyDescriptor;
11 import java.util.HashMap;
12 import java.util.Iterator;
13 import java.util.Locale;
14 import java.util.Map;
15
16 class BeanMapEmitter extends ClassEmitter {
17 private static final Type BEAN_MAP = TypeUtils.parseType(BeanMap.class .getName());
18 private static final Type FIXED_KEY_SET = TypeUtils.parseType(FixedKeySet.class .getName());
19 private static final Signature CSTRUCT_OBJECT = TypeUtils.parseConstructor("Object");
20 private static final Signature CSTRUCT_STRING_ARRAY = TypeUtils.parseConstructor("String[]");
21 private static final Signature BEAN_MAP_GET = TypeUtils.parseSignature("Object get(Object, Object)");
22 private static final Signature BEAN_MAP_PUT = TypeUtils.parseSignature("Object put(Object, Object, Object)");
23 private static final Signature KEY_SET = TypeUtils.parseSignature("java.util.Set keySet()");
24 private static final Signature NEW_INSTANCE = new Signature("newInstance", BEAN_MAP, new Type[]{Constants.TYPE_OBJECT});
25 private static final Signature GET_PROPERTY_TYPE = TypeUtils.parseSignature("Class getPropertyType(String)");
26 private static final Signature CAST_DATA_TYPE = TypeUtils.parseSignature("Object cast(Object,Class)");
27 private static final Signature TO_LOWER_CASE = TypeUtils.parseSignature("String toLowerCase()");
28 private static final Type TYPE_BASIC_DATA_CAST = TypeUtils.parseType(BasicDataCast.class .getName());
29 private final boolean ignoreKeyCase;
30
31 public BeanMapEmitter(ClassVisitor v, String className, Class type, int require, boolean ignoreKeyCase) {
32 super (v);
33 this .ignoreKeyCase = ignoreKeyCase;
34 begin_class(Constants.V1_7, Constants.ACC_PUBLIC, className, BEAN_MAP, null , Constants.SOURCE_FILE);
35 EmitUtils.null_constructor(this );
36 EmitUtils.factory_method(this , NEW_INSTANCE);
37 generateConstructor();
38
39 Map getters = makePropertyMap(ReflectUtils.getBeanGetters(type));
40 Map setters = makePropertyMap(ReflectUtils.getBeanSetters(type));
41 Map allProps = new HashMap<>();
42 allProps.putAll(getters);
43 allProps.putAll(setters);
44
45 if (require != 0) {
46 for (Iterator it = allProps.keySet().iterator(); it.hasNext(); ) {
47 String name = (String) it.next();
48 if ((((require & BeanMap.REQUIRE_GETTER) != 0) && !getters.containsKey(name)) ||
49 (((require & BeanMap.REQUIRE_SETTER) != 0) && !setters.containsKey(name))) {
50 it.remove();
51 getters.remove(name);
52 setters.remove(name);
53 }
54 }
55 }
56 generateGet(type, getters);
57 generatePut(type, setters);
58
59 String[] allNames = getNames(allProps);
60 generateKeySet(allNames);
61 generateGetPropertyType(allProps, allNames);
62 end_class();
63 }
64
65 private String lowerCaseName(String name) {
66 return name.toLowerCase(Locale.US);
67 }
68
69 private String underscoreName(String name) {
70 if (!StringUtils.hasLength(name)) {
71 return "";
72 }
73 StringBuilder result = new StringBuilder();
74 result.append(lowerCaseName(name.substring(0, 1)));
75 for (int i = 1; i < name.length(); i++) {
76 String s = name.substring(i, i + 1);
77 String slc = lowerCaseName(s);
78 if (!s.equals(slc)) {
79 result.append("_").append(slc);
80 } else {
81 result.append(s);
82 }
83 }
84 return result.toString();
85 }
86
87 private Map makePropertyMap(PropertyDescriptor[] props) {
88 Map names = new HashMap<>();
89 for (PropertyDescriptor pd : props) {
90 if (ignoreKeyCase) {
91 names.put(lowerCaseName(pd.getName()), pd);
92 String underscoredName = underscoreName(pd.getName());
93 if (!lowerCaseName(pd.getName()).equals(underscoredName)) {
94 names.put(underscoredName, pd);
95 }
96 } else {
97 names.put(pd.getName(), pd);
98 }
99 }
100 return names;
101 }
102
103 @SuppressWarnings("ToArrayCallWithZeroLengthArrayArgument")
104 private String[] getNames(Map propertyMap) {
105 return (String[]) propertyMap.keySet().toArray(new String[propertyMap.size()]);
106 }
107
108 private void generateConstructor() {
109 CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null );
110 e.load_this();
111 e.load_arg(0);
112 e.super_invoke_constructor(CSTRUCT_OBJECT);
113 e.return_value();
114 e.end_method();
115 }
116
117 private void generateGet(Class type, final Map getters) {
118 final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_GET, null );
119 e.load_arg(0);
120 e.checkcast(Type.getType(type));
121 e.load_arg(1);
122 e.checkcast(Constants.TYPE_STRING);
123 EmitUtils.string_switch(e, getNames(getters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
124 public void processCase(Object key, Label end) {
125 PropertyDescriptor pd = (PropertyDescriptor) getters.get(key);
126 MethodInfo method = ReflectUtils.getMethodInfo(pd.getReadMethod());
127 e.invoke(method);
128 e.box(method.getSignature().getReturnType());
129 e.return_value();
130 }
131
132 public void processDefault() {
133 e.aconst_null();
134 e.return_value();
135 }
136 });
137 e.end_method();
138 }
139
140 private void generatePut(Class type, final Map setters) {
141 final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_PUT, null );
142 e.load_arg(0);
143 e.checkcast(Type.getType(type));
144 e.load_arg(1);
145 e.checkcast(Constants.TYPE_STRING);
146 // 是否忽略大小写
147 if (ignoreKeyCase) {
148 e.invoke_virtual(Constants.TYPE_STRING, TO_LOWER_CASE);
149 }
150 EmitUtils.string_switch(e, getNames(setters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
151 public void processCase(Object key, Label end) {
152 PropertyDescriptor pd = (PropertyDescriptor) setters.get(key);
153 if (pd.getReadMethod() == null ) {
154 e.aconst_null();
155 } else {
156 MethodInfo read = ReflectUtils.getMethodInfo(pd.getReadMethod());
157 e.dup();
158 e.invoke(read);
159 e.box(read.getSignature().getReturnType());
160 }
161 e.swap(); // move old value behind bean
162 e.load_arg(2);
163
164 MethodInfo write = ReflectUtils.getMethodInfo(pd.getWriteMethod());
165 Type setterType = write.getSignature().getArgumentTypes()[0];
166 EmitUtils.load_class(e, setterType);
167 e.invoke_static(TYPE_BASIC_DATA_CAST, CAST_DATA_TYPE);
168 e.box(Constants.TYPE_OBJECT);
169
170 e.unbox(write.getSignature().getArgumentTypes()[0]);
171 e.invoke(write);
172 e.return_value();
173 }
174
175 public void processDefault() {
176 // fall-through
177 }
178 });
179 e.aconst_null();
180 e.return_value();
181 e.end_method();
182 }
183
184 private void generateKeySet(String[] allNames) {
185 // static initializer
186 declare_field(Constants.ACC_STATIC | Constants.ACC_PRIVATE, "keys", FIXED_KEY_SET, null );
187
188 CodeEmitter e = begin_static();
189 e.new_instance(FIXED_KEY_SET);
190 e.dup();
191 EmitUtils.push_array(e, allNames);
192 e.invoke_constructor(FIXED_KEY_SET, CSTRUCT_STRING_ARRAY);
193 e.putfield("keys");
194 e.return_value();
195 e.end_method();
196
197 // keySet
198 e = begin_method(Constants.ACC_PUBLIC, KEY_SET, null );
199 e.load_this();
200 e.getfield("keys");
201 e.return_value();
202 e.end_method();
203 }
204
205 private void generateGetPropertyType(final Map allProps, String[] allNames) {
206 final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_TYPE, null );
207 e.load_arg(0);
208 EmitUtils.string_switch(e, allNames, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
209 public void processCase(Object key, Label end) {
210 PropertyDescriptor pd = (PropertyDescriptor) allProps.get(key);
211 EmitUtils.load_class(e, Type.getType(pd.getPropertyType()));
212 e.return_value();
213 }
214
215 public void processDefault() {
216 e.aconst_null();
217 e.return_value();
218 }
219 });
220 e.end_method();
221 }
222 }