- BeanWrapper是Spring底层经常使用的一个接口,简单来说是对Bean的一种包装,包括对Bean的属性、方法,数据等。
- 唯一的一个实现类是
BeanWrapperImpl
,继承和实现关系图如下:
常用API
public BeanWrapperImpl(Object object)
public BeanWrapperImpl(Class<?> clazz)
public final Object getWrappedInstance()
public PropertyDescriptor getPropertyDescriptor(String propertyName
public PropertyDescriptor[] getPropertyDescriptors()
public Object getPropertyValue(String propertyName)
PropertyDescriptor
- 简称属性描述器,是对属性的封装,包括属性的类型,值,get和set方法,可以通过属性描述器可以很简单的获取和修改对应的值。
- 两个概念如下:
ReadMethod
WriteMethod
实例
- 我们可以同
BeanWrapper
和 PropertyDescriptor
可以很轻松实现属性的复制,下面是本人手写的一个复制的工具类【当然这个是很粗糙的,和BeanUtils中的copyPropreties方法不能相提并论,不喜勿喷】 /**
* 对象复制【浅克隆】
*/
public class NewCopyUtils{
private static final String CLASS="class";
/**
* 复制对象【只能复制基本数据类型,浅克隆】
* @param source 源对象
* @param target 目标对象
* @param ingoreAgrs 忽略的属性
* @throws Exception
*/
public static void copyProperties(Object source,Object target,String... ingoreAgrs)throws Exception {
if (source.getClass().isInterface()||target.getClass().isInterface()){
throw new Exception("source和target不能为接口");
}
BeanWrapper sourceWrap = createBeanWrap(source);
BeanWrapper targetWrap = createBeanWrap(target);
PropertyDescriptor[] targetPds = targetWrap.getPropertyDescriptors();
PropertyDescriptor[] sourcePds = sourceWrap.getPropertyDescriptors();
//根据名称分组,减少一层循环
Map<String, List<PropertyDescriptor>> map = Arrays.asList(sourcePds).parallelStream().filter(o -> !StringUtils.equals(CLASS, o.getName())).collect(Collectors.groupingBy(o -> o.getName()));
for (int i = 0; i < targetPds.length; i++) {
PropertyDescriptor tpd=targetPds[i];
//去掉class属性和不要的复制的属性
if (!StringUtils.equals(CLASS,tpd.getName())&& !Arrays.asList(ingoreAgrs).contains(tpd.getName())){
List<PropertyDescriptor> list = map.getOrDefault(tpd.getName(), null);
if (Objects.nonNull(list)){
Method writeMethod = tpd.getWriteMethod();
Method readMethod = list.get(0).getReadMethod();
if (Objects.isNull(writeMethod)&&Objects.isNull(readMethod)){
throw new Exception("属性必须有get和set方法");
}
Object o = readMethod.invoke(source);
writeMethod.invoke(target,o);
}
}
}
}
/**
* 构造BeanWrapImpl
* @param source 对象
* @return BeanWrapper
*/
private static BeanWrapper createBeanWrap(Object source){
return new BeanWrapperImpl(source);
}
}
原文
https://chenjiabing666.github.io/2019/06/27/BeanWrapper解析/