
sf.tools.reflect.FastBeanUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sorm Show documentation
Show all versions of sorm Show documentation
java jpa tool for spring
The newest version!
package sf.tools.reflect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sf.spring.util.CollectionUtils;
import sf.spring.util.StringUtils;
import sf.tools.reflectasm.MethodAccess;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class FastBeanUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(FastBeanUtils.class);
public static Map, ClassInfo> methodMap = new ConcurrentHashMap<>();
private static Lock classLock = new ReentrantLock();
/**
* 基于get set方法的快速拷贝
* @param source 源对象
* @param target 目标对象
*/
public static void copyProperties(Object source, Object target) {
copyProperties(source, target, false, true);
}
/**
* 基于get set方法的快速拷贝
* 注意此方法拷贝会将所有属性遍历一遍(null的属性可以通过开关设置)
* 默认只会做同名,同类型属性的copier,否则就会报错.
* 注意对于集合类型最好单独处理.
* @param source 源对象
* @param target 目标对象
* @param copyNull 是否拷贝null值
* @param copyMapOrList 是否拷贝集合类型
*/
public static void copyProperties(Object source, Object target, boolean copyNull, boolean copyMapOrList) {
ClassInfo targetASM = methodMap.get(target.getClass());
if (targetASM == null) {
targetASM = cache(target.getClass());
}
ClassInfo sourceASM = methodMap.get(source.getClass());
if (sourceASM == null) {
sourceASM = cache(source.getClass());
}
Map fieldMap = targetASM.infoMap;
for (Map.Entry entry : fieldMap.entrySet()) {
FieldInfo targetInfo = entry.getValue();
Integer targetSetIndex = targetInfo.setterIndex;
FieldInfo sourceInfo = sourceASM.infoMap.get(entry.getKey());
if (sourceInfo != null) {
if (targetInfo.clz != sourceInfo.clz) {//类型不一致,则跳过
continue;
}
if (sourceInfo.isCollection()) {//判断集合类型和集合的泛型是否一致
if (!copyMapOrList) {
continue;
}
Type[] sourceTypes = sourceInfo.actualTypeArguments;
Type[] targetTypes = targetInfo.actualTypeArguments;
boolean canDo = false;
if (targetTypes == null) {
canDo = true;
} else if (sourceTypes != null) {
if (sourceTypes.length == targetTypes.length) {
canDo = true;
for (int i = 0; i < sourceTypes.length; i++) {
if (sourceTypes[i] != targetTypes[i]) {
canDo = false;
break;
}
}
}
}
if (!canDo) {
continue;
}
}
Integer getIndex = sourceInfo.getterIndex;
if (targetSetIndex != null && getIndex != null) {
Object o = sourceASM.getAccess().invoke(source, getIndex);
if (!copyNull && o == null) {
continue;
}
targetASM.getAccess().invoke(target, targetSetIndex, o);
}
}
}
}
/**
* bean转map的快速方法
* @param bean
* @return
*/
public static Map bean2map(Object bean) {
return bean2map(bean, true);
}
/**
* bean转map的快速方法
* @param bean
* @param notNull 是否不为null
* @return
*/
public static Map bean2map(Object bean, boolean notNull) {
if (bean == null) {
return Collections.emptyMap();
}
ClassInfo classInfo = methodMap.get(bean.getClass());
if (classInfo == null) {
classInfo = cache(bean.getClass());
}
Map map = new HashMap<>();
Map fieldMap = classInfo.infoMap;
for (Map.Entry entry : fieldMap.entrySet()) {
FieldInfo fieldInfo = entry.getValue();
Integer getterIndex = fieldInfo.getterIndex;
if (getterIndex != null) {
Object o = classInfo.getAccess().invoke(bean, getterIndex);
if (notNull && o == null) {
continue;
}
map.put(fieldInfo.name, o);
}
}
return map;
}
public static T map2bean(Map map, Class clz) {
if (CollectionUtils.isEmpty(map)) {
return null;
}
//创建一个需要转换为的类型的对象
T obj = null;
ClassInfo classInfo = methodMap.get(clz);
if (classInfo == null) {
classInfo = cache(clz);
}
try {
obj = clz.getDeclaredConstructor().newInstance();
for (Map.Entry entry : classInfo.infoMap.entrySet()) {
FieldInfo fieldInfo = entry.getValue();
Integer setterIndex = fieldInfo.setterIndex;
if (setterIndex != null) {
Object value = map.get(fieldInfo.name);
if (value != null && value.getClass() != fieldInfo.clz) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("bean field=" + fieldInfo.name + ",type=" + fieldInfo.clz
+ " not match map value type=" + value.getClass());
}
continue;
}
classInfo.getAccess().invoke(obj, setterIndex, value);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return obj;
}
// 单例模式
private static ClassInfo cache(Class clz) {
classLock.lock();
try {
ClassInfo reflectASM = new ClassInfo();
MethodAccess methodAccess = MethodAccess.get(clz);
List fields = new ArrayList<>();
Collections.addAll(fields, clz.getDeclaredFields());
List methods = new ArrayList<>();
Collections.addAll(methods, clz.getDeclaredMethods());
Class> clazz = clz.getSuperclass();
for (; clazz != null && clazz != Object.class; clazz = clazz.getSuperclass()) {
Collections.addAll(fields, clazz.getDeclaredFields());
Collections.addAll(methods, clazz.getDeclaredMethods());
}
Map fieldMap = new HashMap<>(fields.size());
for (Field field : fields) {
if (/*Modifier.isPrivate(field.getModifiers())
&&*/ !Modifier.isStatic(field.getModifiers())) { // 是否是私有的,是否是静态的
// 非公共私有变量
String fieldName = StringUtils.capitalize(field.getName()); // 获取属性名称
String getMethodName = null;
if (field.getType() == boolean.class) {
getMethodName = "is" + fieldName;
} else {
getMethodName = "get" + fieldName;
}
String setMethodName = "set" + fieldName;
FieldInfo info = new FieldInfo();
for (Method m : methods) {
if (setMethodName.equals(m.getName()) && m.getParameterCount() == 1) {
info.setterIndex = methodAccess.getIndex(setMethodName);
} else if (getMethodName.equals(m.getName()) && m.getParameterCount() == 0) {
info.getterIndex = methodAccess.getIndex(getMethodName);
}
}
info.name = field.getName();
info.clz = field.getType();
info.collection = Collection.class.isAssignableFrom(info.clz) || Map.class.isAssignableFrom(info.clz);
if (info.collection) {
Type type = field.getGenericType();
if (type instanceof ParameterizedType) {
info.actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
}
}
fieldMap.put(field.getName(), info); // 将属性名称放入集合里
}
}
reflectASM.setAccess(methodAccess);
reflectASM.setInfoMap(fieldMap);
methodMap.put(clz, reflectASM);
return reflectASM;
} finally {
classLock.unlock();
}
}
public static class ClassInfo {
MethodAccess access;
/**
* 字段名称<--->字段属性
*/
Map infoMap = Collections.emptyMap();
public MethodAccess getAccess() {
return access;
}
public void setAccess(MethodAccess access) {
this.access = access;
}
public Map getInfoMap() {
return infoMap;
}
public void setInfoMap(Map infoMap) {
this.infoMap = infoMap;
}
}
public static class FieldInfo {
private Integer setterIndex;
private Integer getterIndex;
private String name;
private Class> clz;
private Type[] actualTypeArguments;
private boolean collection;//是否是集合
public Integer getSetterIndex() {
return setterIndex;
}
public void setSetterIndex(Integer setterIndex) {
this.setterIndex = setterIndex;
}
public Integer getGetterIndex() {
return getterIndex;
}
public void setGetterIndex(Integer getterIndex) {
this.getterIndex = getterIndex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Class> getClz() {
return clz;
}
public void setClz(Class> clz) {
this.clz = clz;
}
public Type[] getActualTypeArguments() {
return actualTypeArguments;
}
public void setActualTypeArguments(Type[] actualTypeArguments) {
this.actualTypeArguments = actualTypeArguments;
}
public boolean isCollection() {
return collection;
}
public void setCollection(boolean collection) {
this.collection = collection;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy