目录

我的学习分享

记录精彩的程序人生

X

使用reflectasm实现bean快速复制(缓存了生成的class对象)

1.导入reflectasm的依赖

	<dependency>
        <groupId>com.esotericsoftware</groupId>
        <artifactId>reflectasm</artifactId>
        <version>1.11.7</version>
    </dependency>

2.浅复制代码

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.esotericsoftware.reflectasm.MethodAccess;

public class BeanCopyUtils {
	private static Map<Class<?>, MethodAccess> methodMap = new HashMap<Class<?>, MethodAccess>();
	private static Map<Class<?>, Map<String, Integer>> methodIndexOfGet = new HashMap<>();
	private static Map<Class<?>, Map<String, Integer>> methodIndexOfSet = new HashMap<>();
	private static Map<Class<?>, Map<String, String>> methodIndexOfType = new HashMap<>();

	/**
	 * 浅copy类属性,根据属性名匹配,而不是类型+属性匹配,当类型不同且原属性值为null时,不变动目标类此属性值
	 * 
	 * @param desc
	 *            接收复制参数的类
	 * @param orgi
	 *            原始类
	 */
	public static void copyProperties(Object desc, Object orgi) {
		MethodAccess descMethodAccess = methodAccessFactory(desc);
		MethodAccess orgiMethodAccess = methodAccessFactory(orgi);
		Map<String, Integer> get = methodIndexOfGet.get(orgi.getClass());
		Map<String, Integer> set = methodIndexOfSet.get(desc.getClass());
		Map<String, String> oritypemap = methodIndexOfType.get(orgi.getClass());
		Map<String, String> desctypemap = methodIndexOfType.get(desc.getClass());

		List<String> sameField = null;
		if (get.size() < set.size()) {
			sameField = new ArrayList<>(get.keySet());
			sameField.retainAll(set.keySet());
		} else {
			sameField = new ArrayList<>(set.keySet());
			sameField.retainAll(get.keySet());
		}
		for (String field : sameField) {
			Integer setIndex = set.get(field);
			Integer getIndex = get.get(field);
			String oritype = oritypemap.get(field);
			String desctype = desctypemap.get(field);
			Object value = orgiMethodAccess.invoke(orgi, getIndex);
			try {
				if (!oritype.equalsIgnoreCase(desctype)) {
					if (value == null) {
						continue;
					}
					switch (desctype) {
					case "java.lang.String":
						descMethodAccess.invoke(desc, setIndex.intValue(), value.toString());
						break;
					case "java.lang.Integer":
					case "int":
						descMethodAccess.invoke(desc, setIndex.intValue(), Integer.valueOf(value.toString()));
						break;
					case "java.lang.Long":
					case "long":
						descMethodAccess.invoke(desc, setIndex.intValue(), Long.valueOf(value.toString()));
						break;
					case "java.lang.Float":
					case "float":
						descMethodAccess.invoke(desc, setIndex.intValue(), Long.valueOf(value.toString()));
						break;
					case "java.lang.Boolean":
					case "boolean":
						descMethodAccess.invoke(desc, setIndex.intValue(), Boolean.valueOf(value.toString()));
						break;
					case "java.lang.Double":
					case "double":
						descMethodAccess.invoke(desc, setIndex.intValue(), Double.valueOf(value.toString()));
						break;
					case "java.lang.Byte":
					case "byte":
						descMethodAccess.invoke(desc, setIndex.intValue(), Byte.valueOf(value.toString()));
						break;
					case "java.lang.Short":
					case "short":
						descMethodAccess.invoke(desc, setIndex.intValue(), Short.valueOf(value.toString()));
						break;
					default:
						break;
					}
				} else {
					descMethodAccess.invoke(desc, setIndex.intValue(), value);
				}
			} catch (Exception e) {
				System.out.println(field + ":" + e.getMessage());
			}
		}
	}

	// double check
	private static MethodAccess methodAccessFactory(Object obj) {
		MethodAccess descMethodAccess = methodMap.get(obj.getClass());
		if (descMethodAccess == null) {
			synchronized (obj.getClass()) {
				descMethodAccess = methodMap.get(obj.getClass());
				if (descMethodAccess != null) {
					return descMethodAccess;
				}
				Class<?> c = obj.getClass();
				MethodAccess methodAccess = MethodAccess.get(c);
				Field[] fields = c.getDeclaredFields();
				Map<String, Integer> indexofget = new HashMap<>();
				Map<String, Integer> indexofset = new HashMap<>();
				Map<String, String> indexoftype = new HashMap<>();
				for (Field field : fields) {
					if (Modifier.isPrivate(field.getModifiers()) && !Modifier.isStatic(field.getModifiers())) { // 私有非静态
						String fieldName = captureName(field.getName()); // 获取属性名称
						int getIndex = methodAccess.getIndex("get" + fieldName); // 获取get方法的下标
						int setIndex = methodAccess.getIndex("set" + fieldName); // 获取set方法的下标
						indexofget.put(fieldName, getIndex);
						indexofset.put(fieldName, setIndex);
						indexoftype.put(fieldName, field.getType().getName());
					}
				}
				methodIndexOfGet.put(c, indexofget);
				methodIndexOfSet.put(c, indexofset);
				methodIndexOfType.put(c, indexoftype);
				methodMap.put(c, methodAccess);
				return methodAccess;
			}
		}
		return descMethodAccess;
	}

	private static String captureName(String name) {
		char[] cs = name.toCharArray();
		cs[0] -= 32;
		return String.valueOf(cs);
	}
}

————————————————
版权声明:本文为CSDN博主「土豆番茄酱紫」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wyyrockking/article/details/84525440


自己改了一版

package xxx.util;

package xxx.util;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.esotericsoftware.reflectasm.MethodAccess;

/**
 * @see http://acuilab.com:8080/articles/2020/05/26/1590461350391.html
 * @author admin
 */
public class BeanCopyUtils {

    private static Map<Class<?>, MethodAccess> methodMap = new HashMap<Class<?>, MethodAccess>();
    private static Map<Class<?>, Map<String, Integer>> methodIndexOfGet = new HashMap<>();
    private static Map<Class<?>, Map<String, Integer>> methodIndexOfSet = new HashMap<>();
    private static Map<Class<?>, Map<String, String>> methodIndexOfType = new HashMap<>();

    /**
     * 浅copy类属性, 当类型相同且原属性值为不为null时,才变动目标类此属性值
     *
     * @param dest 目标类
     * @param orgi 原始类
     */
    public static void copyProperties(Object dest, Object orgi) {
	MethodAccess destMethodAccess = methodAccessFactory(dest);
	MethodAccess orgiMethodAccess = methodAccessFactory(orgi);
	Map<String, Integer> get = methodIndexOfGet.get(orgi.getClass());
	Map<String, Integer> set = methodIndexOfSet.get(dest.getClass());
	Map<String, String> oritypemap = methodIndexOfType.get(orgi.getClass());
	Map<String, String> desctypemap = methodIndexOfType.get(dest.getClass());

	List<String> sameField = null;
	if (get.size() < set.size()) {
	    sameField = new ArrayList<>(get.keySet());
	    sameField.retainAll(set.keySet());
	} else {
	    sameField = new ArrayList<>(set.keySet());
	    sameField.retainAll(get.keySet());
	}
	
	for (String field : sameField) {
	    Integer setIndex = set.get(field);
	    Integer getIndex = get.get(field);
	    String oritype = oritypemap.get(field);
	    String desttype = desctypemap.get(field);
	    Object value = orgiMethodAccess.invoke(orgi, getIndex);
	    
	    if (oritype.equalsIgnoreCase(desttype)) {
		if (value == null) {
		    continue;
		}
		
		destMethodAccess.invoke(dest, setIndex, value);
	    }
	}
    }

    // double check
    private static MethodAccess methodAccessFactory(Object obj) {
	MethodAccess descMethodAccess = methodMap.get(obj.getClass());
	if (descMethodAccess == null) {
	    synchronized (obj.getClass()) {
		descMethodAccess = methodMap.get(obj.getClass());
		if (descMethodAccess != null) {
		    return descMethodAccess;
		}
		Class<?> c = obj.getClass();
		MethodAccess methodAccess = MethodAccess.get(c);
		Field[] fields = c.getDeclaredFields();
		Map<String, Integer> indexofget = new HashMap<>();
		Map<String, Integer> indexofset = new HashMap<>();
		Map<String, String> indexoftype = new HashMap<>();
		for (Field field : fields) {
		    if (Modifier.isPrivate(field.getModifiers()) && !Modifier.isStatic(field.getModifiers())) { // 私有非静态
			String fieldName = captureName(field.getName()); // 获取属性名称
			try {
			    int getIndex = methodAccess.getIndex("get" + fieldName); // 获取get方法的下标
			    indexofget.put(fieldName, getIndex);
			} catch(java.lang.IllegalArgumentException ex) {
			    // 布尔型属性
			    int getIndex = methodAccess.getIndex("is" + fieldName);
			    indexofget.put(fieldName, getIndex);
			}
			
			int setIndex = methodAccess.getIndex("set" + fieldName); // 获取set方法的下标
			indexofset.put(fieldName, setIndex);
			indexoftype.put(fieldName, field.getType().getName());
		    }
		}
		methodIndexOfGet.put(c, indexofget);
		methodIndexOfSet.put(c, indexofset);
		methodIndexOfType.put(c, indexoftype);
		methodMap.put(c, methodAccess);
		return methodAccess;
	    }
	}
	return descMethodAccess;
    }

    private static String captureName(String name) {
	char[] cs = name.toCharArray();
	cs[0] -= 32;
	return String.valueOf(cs);
    }
}