源码解读之(七)BeanUtils(1)

public class CopyTest {

public static void main(String[] args) {

Image image = new Image();

image.setNewsId(“1001”);

image.setTitle(“全明星正赛 勒布朗队-字母哥队”);

image.setVideo(true);

image.setShowTime(109.48);

image.setTag(“NBA”);

image.setTopicVex(“东西部对决”);

image.setClassification(“NBA”);

image.setSubClassification(“全明星赛”);

Image2 targetImage = new Image2();

BeanUtils.copyProperties(image, targetImage);

System.out.println(targetImage.toString());

}

}

输出结果:

Image2{newsId=‘1001’, title=‘全明星正赛 勒布朗队-字母哥队’, isVideo=true, showTime=109.48, tag=‘NBA’}

这两种方式的输出结果,小伙伴们应该也发现了。第二种方式输出的字段少了一些,这是因为 Image2 里的字段属性比 Image 少几个。

3、小结

如果你的目标对象不需要复制源对象中的所有属性的话,你就用 BeanUtils.copyProperties,否则用clone()方法就能满足。

二、源码解析


本篇的重点是第二种方式,下面我们就来从源码层面来分析,博主用的是 JDK 1.8

// 将给定源bean的属性值赋值到目标bean中

public static void copyProperties(Object source, Object target, String… ignoreProperties) throws BeansException {

copyProperties(source, target, (Class)null, ignoreProperties);

}

private static void copyProperties(Object source, Object target, @Nullable Class<?> editable, @Nullable String… ignoreProperties) throws BeansException {

Assert.notNull(source, “Source must not be null”);

Assert.notNull(target, “Target must not be null”);

Class<?> actualEditable = target.getClass();

if (editable != null) {

if (!editable.isInstance(target)) {

throw new IllegalArgumentException(“Target class [” + target.getClass().getName() + “] not assignable to Editable class [” + editable.getName() + “]”);

}

actualEditable = editable;

}

// 1、调用Java内省API,获取PropertyDescriptor。

PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);

List ignoreList = ignoreProperties != null ? Arrays.asList(ignoreProperties) : null;

PropertyDescriptor[] var7 = targetPds;

int var8 = targetPds.length;

// 2、轮询目标bean的PropertyDescriptor

for(int var9 = 0; var9 < var8; ++var9) {

PropertyDescriptor targetPd = var7[var9];

Method writeMethod = targetPd.getWriteMethod();

// 判断是否存在setter方法以及属性是否在需要忽略的属性列表中

if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {

// 获取源bean的PropertyDescriptor

PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());

if (sourcePd != null) {

// 获取源bean的PropertyDescriptor

Method readMethod = sourcePd.getReadMethod();

// 判断是否可赋值

if (readMethod != null && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {

try {

// 如果getter方法不是public,则需要设置其accessible

if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {

readMethod.setAccessible(true);

}

// 通过反射获取source对象属性的值

Object value = readMethod.invoke(source);

// 如果setter方法不是public则需要设置其accessible

if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {

writeMethod.setAccessible(true);

}

// 通过反射给target对象属性赋值

writeMethod.invoke(target, value);

} catch (Throwable va

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值