Files
cooperop-app/cooperop-app-common/src/main/java/business/cooperop/common/utils/BeanUtilsV2.java
2021-01-20 18:26:47 +08:00

259 lines
9.8 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package business.cooperop.common.utils;
/*
**********************************************
* DATE PERSON REASON
* 2020/9/4 FXY Created
**********************************************
*/
import com.esotericsoftware.reflectasm.MethodAccess;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 待重写
*/
public class BeanUtilsV2 {
/**
* 通过 ASM反射 速度比 Spring BeanUtils.copyProperties(source,target) 快一倍
* 类型不同可以转换
* 大小写可以忽略
* 下划线 _ 被忽略
* fxy备注需要操纵字节码服务器没有性能瓶颈的情况下慎用
*
* @param source 数据源
* @param target 目标是数据
* @param <T>
* @return
*/
public static <T> T copyPropertiesASM(Object source, Object target) {
MethodAccess sourceMethodAccess = CacheMethodAccess.getMethodAccess(source.getClass());
MethodAccess targetMethodAccess = CacheMethodAccess.getMethodAccess(target.getClass());
Map<String, String> sourceGet = CacheAsmFiledMethod.getMethod("get", source.getClass());
Map<String, String> targetSet = CacheAsmFiledMethod.getMethod("set", target.getClass());
CacheFieldMap.getFieldMap(target.getClass()).keySet().forEach((it) -> {
String sourceIndex = sourceGet.get(it);
if (sourceIndex != null) {
Object value = sourceMethodAccess.invoke(source, sourceIndex);
String setIndex = targetSet.get(it);
targetMethodAccess.invoke(target, setIndex, value);
}
});
return (T) target;
}
/**
* 模仿Spring中 BeanUtils.copyProperties(source,target)
* 目前仅支持整形到布尔类型的单向转换
* 但是
* 大小写可以忽略
* 下划线 _ 被忽略
*
* @param source
* @param target
* @param <T>
* @return
*/
public static <T> T copyProperties(Object source, Object target) {
Map<String, Field> sourceMap = CacheFieldMap.getFieldMap(source.getClass());
CacheFieldMap.getFieldMap(target.getClass()).values().forEach((it) -> {
Field field = sourceMap.get(it.getName().toLowerCase().replace("_", ""));
if (field != null) {
it.setAccessible(true);
field.setAccessible(true);
try {
if (field.getType() == Integer.class && it.getType() == Boolean.class) {
it.set(target, (Integer) field.get(source) == 1 ? true : false);
} else {
it.set(target, field.get(source));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} finally {
//及时关闭访问权限
field.setAccessible(false);
it.setAccessible(false);
}
}
});
return (T) target;
}
/**
* @param source 源对象
* @param target 目标对象
* @param ignores 需要忽略的字段数组元素
* @param <T> 返回赋了值的目标对象
* 目前不同类型之间的转换,仅支持整形向布尔类型的单向转换
* @return
*/
public static <T> T copyProperties(Object source, Object target, String... ignores) {
Map<String, Field> sourceMap = CacheFieldMap.getFieldMap(source.getClass(), ignores);
CacheFieldMap.getFieldMap(target.getClass()).values().forEach((it) -> {
Field field = sourceMap.get(it.getName().toLowerCase().replace("_", ""));
if (field != null) {
it.setAccessible(true);
field.setAccessible(true);
try {
if (field.getType() == Integer.class && it.getType() == Boolean.class) {
it.set(target, (Integer) field.get(source) == 1 ? true : false);
} else {
it.set(target, field.get(source));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} finally {
field.setAccessible(false);
it.setAccessible(false);
}
}
});
return (T) target;
}
/**
* Asm方式缓存变量域到map中待优化
* 可以将加锁操作换做无阻塞的并发容器
*/
private static class CacheAsmFiledMethod {
private static Map<String, Map<String, String>> cacheGetMethod = new HashMap<>();
private static Map<String, Map<String, String>> cacheSetMethod = new HashMap<>();
private static Map<String, String> getMethod(String type, Class clazz) {
MethodAccess methodAccess = CacheMethodAccess.getMethodAccess(clazz);
Map<String, Field> allFields = CacheFieldMap.getFieldMap(clazz);
Map<String, String> result = null;
if (type.equals("get")) {
result = cacheGetMethod.get(clazz.getName());
} else if (type.equals("set")) {
result = cacheSetMethod.get(clazz.getName());
}
if (result == null) {
synchronized (CacheAsmFiledMethod.class) {
if (result == null) {
Map<String, String> set = new HashMap<>();
Map<String, String> get = new HashMap<>();
allFields.values().forEach((it) -> {
//判断是否是静态
if (!Modifier.isStatic(it.getModifiers())) {
//首字母大写
char[] f = it.getName().toCharArray();
f[0] -= 32;
String fieldName = new String(f);
get.put(fieldName.toLowerCase().replace("_", ""), "get" + fieldName);
set.put(fieldName.toLowerCase().replace("_", ""), "set" + fieldName);
}
});
cacheGetMethod.put(clazz.getName(), get);
cacheSetMethod.put(clazz.getName(), set);
if (type.equals("get")) {
result = cacheGetMethod.get(clazz.getName());
} else if (type.equals("set")) {
result = cacheSetMethod.get(clazz.getName());
}
}
}
}
return result;
}
}
/**
* 缓存方法访问权限容器,加锁操作待优化
*/
private static class CacheMethodAccess {
private CacheMethodAccess() {
}
private static Map<String, MethodAccess> cache = new HashMap<>();
private static MethodAccess getMethodAccess(Class clazz) {
MethodAccess result = cache.get(clazz.getName());
if (result == null) {
synchronized (CacheMethodAccess.class) {
if (result == null) {
cache.put(clazz.getName(), MethodAccess.get(clazz));
result = cache.get(clazz.getName());
}
}
}
return result;
}
}
/**
* 缓存所有域到map中加锁操作待优化
*/
private static class CacheFieldMap {
private static Map<String, Map<String, Field>> cacheMap = new HashMap<>();
private static Map<String, Field> getFieldMap(Class clazz) {
Map<String, Field> result = cacheMap.get(clazz.getName());
if (result == null) {
synchronized (CacheFieldMap.class) {
if (result == null) {
List<Field> allFields = getAllFields(clazz);
Map<String, Field> fieldMap = allFields.stream().collect(Collectors.toMap(field -> field.getName().toLowerCase().replace("_", ""), Function.<Field>identity()));
cacheMap.put(clazz.getName(), fieldMap);
result = cacheMap.get(clazz.getName());
}
}
}
return result;
}
/**
* 每次反射完成后将数据存放在内存中
*
* @param clazz
* @param ignores
* @return
*/
private static Map<String, Field> getFieldMap(Class clazz, String... ignores) {
Map<String, Field> result = cacheMap.get(clazz.getName());
List<String> list = Arrays.asList(ignores);
if (result == null) {
synchronized (CacheFieldMap.class) {
if (result == null) {
List<Field> allFields = getAllFields(clazz);
Map<String, Field> fieldMap = allFields.stream().filter(a -> !(list.contains(a.getName()))).collect(Collectors.toMap(field -> field.getName().toLowerCase().replace("_", ""), Function.<Field>identity()));
cacheMap.put(clazz.getName(), fieldMap);
result = cacheMap.get(clazz.getName());
}
}
}
return result;
}
}
/**
* 得到包括继承而来的所有域
*
* @param clazz
* @return
*/
private static List<Field> getAllFields(Class clazz) {
List<Field> fieldList = new ArrayList<>();
while (clazz != null && !clazz.getName().toLowerCase().equals("java.lang.object")) {
fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
clazz = clazz.getSuperclass();
}
return fieldList;
}
}