工具类--BeanUtils----Bean转换工具

  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<String, BeanCopier> BEAN_COPIER_MAP = new ConcurrentHashMap<>();
 32     private static final Map<String, BeanCopier> NONE_NULL_BEAN_COPIER_MAP = new ConcurrentHashMap<>();
 33 
 34     /**
 35      * MAP集合转成bean对象集合
 36      *
 37      * @param listResult 需要拷贝的集合
 38      * @param clazz      需要将map转换成的Class
 39      * @param <B>        泛型
 40      * @return 集合泛型
 41      * @author zhouyy
 42      */
 43     public static <B> List<B> copyMapListProperties(List listResult, Class<B> clazz) {
 44         List<B> sourceList = new ArrayList<>();
 45         Map<String, Object> 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<String, Object> newMap = new HashMap<>();
 54 //                Iterator<Map.Entry<String, Object>> entries = map.entrySet().iterator();
 55 //                while (entries.hasNext()) {
 56 //                    Map.Entry<String, Object> 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 <B>
 72      * @return
 73      * @author zhouyy
 74      */
 75     public static <B> B copyMapProperties(Map map, Class<B> clazz) {
 76         Map<String, Object> 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<Field> 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 <B>
102      * @return
103      * @author zhouyy
104      */
105     @SuppressWarnings("unchecked")
106     private static <B> B copyMapProperties(Map map, Class<B> clazz, Map<String, Object> 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<Field> fieldList = (List<Field>) 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<Map.Entry<String, Object>> it = map.entrySet().iterator();
129 //        while (it.hasNext()) {
130 //            Map.Entry<String, Object> 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<Bean>
209      *
210      * @param source list集合
211      * @param t      所成对象的class
212      * @param <B>
213      * @return List<T>
214      * @throws BeansException
215      */
216     public static <S, B> List<B> copyListProperties(List<S> source, Class<B> t) throws BeansException {
217         List<B> 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<B> 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<String, Object> beanToMap(Object obj) {
248         BeanMap beanMap = BeanMap.create(obj);
249         HashMap<String, Object> 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<String, Object> 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<Map<String, Object>> mergeListBeanToMap(List<?> listA, List<?> listB, String key) {
287         List<Map<String, Object>> list = new ArrayList<>();
288         for (Object objA : listA) {
289             //将对象转换为Map
290             Map<String, Object> mapA = beanToMap(objA);
291             for (Object objB : listB) {
292                 //将对象转换为Map
293                 Map<String, Object> 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<String, Object> mergeBeanToMap(Object objA, Object objB, String key) {
316         if (objA == null) {
317             return null;
318         }
319         Map<String, Object> mapA = beanToMap(objA);
320         if (objB == null) {
321             return mapA;
322         }
323         Map<String, Object> 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> B copyNewInstanceProperties(Object source, Class<B> 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<String> 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<Object, Object> 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 <code>Map</code>-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 <code>null</code>. 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 <code>BeanMap</code>.  For finer
 40      * control over the generated instance, use a new instance of
 41      * <code>BeanMap.Generator</code> instead of this static method.
 42      *
 43      * @param bean the JavaBean underlying the map
 44      * @return a new <code>BeanMap</code> 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 <code>BeanMap</code>. 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 <code>BeanMap</code> 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 <code>BeanMap</code> 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 <code>BeanMap</code>
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 <code>BeanMap</code>
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 <code>BeanMap</code>
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<Object, Object> 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<Object> 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<Object, Object> 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<Object, Object> 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 }

 

posted @ 2019-11-07 21:11  _万古如长夜  阅读(1958)  评论(0编辑  收藏  举报