在Java开发中,数据拷贝是一项非常常见的任务。Apache Commons BeanUtils库提供了一种方便的方式来实现JavaBean之间的属性拷贝。然而,当涉及到拷贝List类型的属性时,BeanUtils的默认实现会遇到一些限制。本文将介绍如何通过改造BeanUtils来优雅地实现List数据拷贝。
1. BeanUtils的默认实现
首先,让我们来看一下BeanUtils的默认实现。假设我们有两个JavaBean,分别为SourceBean和TargetBean:
public class SourceBean {
private List<String> items;
public List<String> getItems() {
return items;
}
public void setItems(List<String> items) {
this.items = items;
}
}
public class TargetBean {
private List<String> items;
public List<String> getItems() {
return items;
}
public void setItems(List<String> items) {
this.items = items;
}
}
我们可以使用BeanUtils.copyProperties()方法将SourceBean的属性拷贝到TargetBean中:
SourceBean source = new SourceBean();
source.setItems(Arrays.asList("item1", "item2", "item3"));
TargetBean target = new TargetBean();
BeanUtils.copyProperties(target, source);
System.out.println(target.getItems()); // [item1, item2, item3]
这段代码可以正常工作,但是如果我们尝试修改TargetBean的items属性,会发现它会影响到SourceBean的items属性:
target.getItems().add("item4");
System.out.println(source.getItems()); // [item1, item2, item3, item4]
这是因为BeanUtils默认情况下只是简单地将List对象的引用复制到目标对象中,而不是创建一个新的List对象。因此,当我们修改目标对象中的List时,源对象中的List也会被修改。
2. 改造BeanUtils
为了解决这个问题,我们需要改造BeanUtils。具体来说,我们需要扩展BeanUtils.copyProperty()方法,以便在拷贝List类型属性时创建一个新的List对象。
首先,我们需要创建一个新的类ListConverter,它实现了org.apache.commons.beanutils.Converter接口:
public class ListConverter implements Converter {
@SuppressWarnings("rawtypes")
@Override
public Object convert(Class type, Object value) {
if (value == null) {
return null;
} else if (value instanceof List) {
List<?> list = (List<?>) value;
List<Object> copy = new ArrayList<>(list.size());
for (Object item : list) {
copy.add(item);
}
return copy;
} else {
throw new ConversionException("Cannot convert " + value.getClass().getName() + " to List");
}
}
}
这个类的作用是在拷贝List类型属性时创建一个新的List对象。如果属性值为null,则返回null;如果属性值为List类型,则遍历原始List并将其元素添加到新的List中;否则抛出ConversionException异常。
接下来,我们需要注册这个Converter。可以通过以下方式进行注册:
ConvertUtils.register(new ListConverter(), List.class);
这样就完成了Converter的注册。现在我们可以使用改造后的BeanUtils来拷贝List类型属性了:
SourceBean source = new SourceBean();
source.setItems(Arrays.asList("item1", "item2", "item3"));
TargetBean target = new TargetBean();
BeanUtils.copyProperties(target, source);
System.out.println(target.getItems()); // [item1, item2, item3]
target.getItems().add("item4");
System.out.println(source.getItems()); // [item1, item2, item3]
现在修改目标对象中的List不会影响源对象中的List了。
3. 总结
在Java开发中,数据拷贝是一项非常常见的任务。Apache Commons BeanUtils库提供了一种方便的方式来实现JavaBean之间的属性拷贝。然而,当涉及到拷贝List类型的属性时,BeanUtils的默认实现会遇到一些限制。通过改造BeanUtils并注册一个新的Converter,我们可以优雅地实现List数据拷贝。