com.xiaoleilu.hutool.bean.copier.BeanCopier Maven / Gradle / Ivy
package com.xiaoleilu.hutool.bean.copier;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import com.xiaoleilu.hutool.bean.BeanUtil;
import com.xiaoleilu.hutool.bean.copier.provider.BeanValueProvider;
import com.xiaoleilu.hutool.bean.copier.provider.MapValueProvider;
import com.xiaoleilu.hutool.collection.CollectionUtil;
import com.xiaoleilu.hutool.bean.BeanDesc.PropDesc;
import com.xiaoleilu.hutool.convert.Convert;
import com.xiaoleilu.hutool.exceptions.UtilException;
import com.xiaoleilu.hutool.lang.copier.Copier;
import com.xiaoleilu.hutool.map.MapUtil;
import com.xiaoleilu.hutool.util.StrUtil;
import com.xiaoleilu.hutool.util.TypeUtil;
/**
* Bean拷贝
* @author looly
*
* @param 目标对象类型
* @since 3.2.3
*/
public class BeanCopier implements Copier{
private Object source;
private T dest;
private CopyOptions copyOptions;
/**
* 创建BeanCopier
*
* @param 目标Bean类型
* @param source 来源对象,可以是Bean或者Map
* @param dest 目标Bean对象
* @param copyOptions 拷贝属性选项
* @return BeanCopier
*/
public static BeanCopier create(Object source, T dest, CopyOptions copyOptions){
return new BeanCopier<>(source, dest, copyOptions);
}
/**
* 构造
*
* @param source 来源对象,可以是Bean或者Map
* @param dest 目标Bean对象
* @param copyOptions 拷贝属性选项
*/
public BeanCopier(Object source, T dest, CopyOptions copyOptions) {
this.source = source;
this.dest = dest;
this.copyOptions = copyOptions;
}
@Override
@SuppressWarnings("unchecked")
public T copy() {
if(null != this.source) {
if(this.source instanceof ValueProvider) {
valueProviderToBean((ValueProvider)this.source, this.dest);
}else if(this.source instanceof Map) {
mapToBean((Map, ?>)this.source, this.dest);
}else {
beanToBean(this.source, this.dest);
}
}
return this.dest;
}
/**
* Bean和Bean之间属性拷贝
* @param providerBean 来源Bean
* @param destBean 目标Bean
*/
private void beanToBean(Object providerBean, Object destBean) {
valueProviderToBean(new BeanValueProvider(providerBean, this.copyOptions.ignoreCase, this.copyOptions.ignoreError), destBean);
}
/**
* Map转Bean属性拷贝
* @param map Map
* @param bean Bean
*/
private void mapToBean(Map, ?> map, Object bean) {
valueProviderToBean(new MapValueProvider(map, this.copyOptions.ignoreCase), bean);
}
/**
* 值提供器转Bean
*
* @param valueProvider 值提供器
* @param bean Bean
*/
private void valueProviderToBean(ValueProvider valueProvider, Object bean) {
if (null == valueProvider) {
return;
}
Class> actualEditable = bean.getClass();
if (copyOptions.editable != null) {
// 检查限制类是否为target的父类或接口
if (false == copyOptions.editable.isInstance(bean)) {
throw new IllegalArgumentException(StrUtil.format("Target class [{}] not assignable to Editable class [{}]", bean.getClass().getName(), copyOptions.editable.getName()));
}
actualEditable = copyOptions.editable;
}
final HashSet ignoreSet = null != (copyOptions.ignoreProperties) ? CollectionUtil.newHashSet(copyOptions.ignoreProperties) : null;
final Map fieldReverseMapping = (null != copyOptions.fieldMapping) ? MapUtil.reverse(copyOptions.fieldMapping) : null;
final Collection props = BeanUtil.getBeanDesc(actualEditable).getProps();
String fieldName;
Object value;
Method setterMethod;
Class> propClass;
for (PropDesc prop : props) {
// 获取值
fieldName = prop.getFieldName();
if ((null != ignoreSet && ignoreSet.contains(fieldName)) || false == valueProvider.containsKey(fieldName)) {
// 属性值被忽略或值提供者无此key时跳过
continue;
}
setterMethod = prop.getSetter();
if(null == setterMethod) {
//Setter方法不存在跳过
continue;
}
// 此处对valueProvider传递的为Type对象,而非Class,因为Type中包含泛型类型信息
String providerKey = null;
if(null != fieldReverseMapping) {
providerKey = fieldReverseMapping.get(fieldName);
}
if(null == providerKey) {
providerKey = fieldName;
}
value = valueProvider.value(providerKey, TypeUtil.getFirstParamType(setterMethod));
if (null == value && copyOptions.ignoreNullValue) {
continue;// 当允许跳过空时,跳过
}
try {
// valueProvider在没有对值做转换且当类型不匹配的时候,执行默认转换
propClass = prop.getFieldClass();
if (false == propClass.isInstance(value)) {
value = Convert.convert(propClass, value);
if (null == value && copyOptions.ignoreNullValue) {
continue;// 当允许跳过空时,跳过
}
}
// 执行set方法注入值
if (null != setterMethod) {
setterMethod.invoke(bean, value);
}
} catch (Exception e) {
if (copyOptions.ignoreError) {
continue;// 忽略注入失败
} else {
throw new UtilException(e, "Inject [{}] error!", prop.getFieldName());
}
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy