Spring中BeanUtils.copyProperties方法测试

本文详细解释了属性复制的概念,并通过实例展示了如何使用BeanUtils工具类实现不同对象间属性的复制。包括属性值少的复制给属性值多的对象、属性值多的复制给属性值少的对象及不同类型的属性复制时可能出现的类型匹配错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

copyProperties顾名思义是复制属性,就是把A对象的属性复制给B对象的与之相同的属性。下面的属性省略Getter,Setter。


public class UserOne
{
private int id;
private String name;

@Override
public String toString()
{
return id + "......." + name;
}
}


public class UserTwo
{
private int id;
private String name;
private String address;

@Override
public String toString()
{
return id + "......." + name + "........" + address;
}
}

public class UserThree
{
private String id;
private String name;
private String address;

@Override
public String toString()
{
return id + "......." + name + "........" + address;
}
}


import org.springframework.beans.BeanUtils;

public class Test
{
public static void main(String[] args)
{
LessToMore();
MoreToLess();
ArgusMisMatch();
}

// 属性值少的复制给属性值多的,没有被复制到的属性就是该类型的默认值。结果1......xy......null
public static void LessToMore()
{
UserOne u1 = new UserOne();
u1.setId(1);
u1.setName("xy");
UserTwo u2 = new UserTwo();
BeanUtils.copyProperties(u1, u2);
System.out.println(u2);
}



// 属性值多的复制给属性值少的。结果1......xy
public static void MoreToLess()
{
UserTwo u2 = new UserTwo();
u2.setId(1);
u2.setName("xy");
u2.setAddress("aa");
UserOne u1 = new UserOne();

BeanUtils.copyProperties(u2, u1);
System.out.println(u1);
}



// 报错argument type mismatch。u2的id类型是int,u3的id类型是String
public static void ArgusMisMatch()
{
UserTwo u2 = new UserTwo();
u2.setId(1);
u2.setName("xy");
u2.setAddress("aa");
UserThree u3 = new UserThree();
BeanUtils.copyProperties(u2, u3);
System.out.println(u3);
}
}

总结一下

A对象把与同名且同类型的属性复制给B对象的属性。

没有同名的,B对象的没有被复制值的属性为该类型的默认值。

同名但类型不同,会报错:argument type mismatch

### BeanUtils.copyProperties 方法的循环引用处理 `BeanUtils.copyProperties` 方法Spring 框架中主要用于将一个对象的属性值复制到另一个对象。然而,该方法并未提供对循环引用的内置处理机制[^1]。如果源对象或目标对象存在循环引用(例如,对象 A 引用了对象 B,而对象 B 又引用了对象 A),调用 `BeanUtils.copyProperties` 时可能会导致堆栈溢出错误(`StackOverflowError`)或无限递归。 #### 循环引用的定义 循环引用是指两个或多个对象之间存在相互引用的关系。例如: ```java public class Person { private String name; private Person friend; // getters and setters } ``` 在这种情况下,如果 `Person A` 的 `friend` 属性指向 `Person B`,而 `Person B` 的 `friend` 属性又指向 `Person A`,就会形成循环引用。 #### BeanUtils.copyProperties 的行为 当使用 `BeanUtils.copyProperties` 方法时,它通过反射机制访问源对象的 getter 方法,并将结果设置到目标对象的 setter 方法中。如果遇到循环引用的对象结构,`BeanUtils.copyProperties` 不会自动检测或处理这种关系,而是继续递归地复制属性值,最终可能导致程序崩溃[^2]。 #### 替代方案 为了避免循环引用问题,可以考虑以下几种替代方案: 1. **手动复制属性** 使用简单的 setter 方法手动复制属性值,而不是依赖 `BeanUtils.copyProperties`。这种方式虽然繁琐,但可以完全避免循环引用问题。 2. **使用 MapStruct 或 ModelMapper** 这些库提供了更高级的对象映射功能,并支持自定义配置以处理复杂的对象结构,包括循环引用。例如,MapStruct 提供了 `@Mapping` 注解和 `@AfterMapping` 方法,可以显式定义如何处理循环引用[^3]。 3. **深度克隆与缓存机制** 在复制对象时,可以引入缓存机制来记录已经处理过的对象实例。如果再次遇到相同对象,则直接从缓存中获取,而不是重复递归。这种方式需要开发者自行实现或选择支持此功能的第三方库。 #### 示例代码:手动处理循环引用 以下是一个使用 MapStruct 处理循环引用的示例: ```java @Mapper public interface PersonMapper { @Mappings({ @Mapping(target = "friend", qualifiedByName = "avoidCircularReference") }) TargetPerson sourceToTarget(SourcePerson source); default TargetPerson avoidCircularReference(SourcePerson source) { if (source == null) { return null; } // 返回简化的对象以避免循环引用 return new TargetPerson(source.getName(), null); } } ``` ### 总结 `BeanUtils.copyProperties` 方法本身不支持循环引用的处理[^1]。如果应用程序中可能存在循环引用的对象结构,建议使用其他更强大的对象映射工具(如 MapStruct 或 ModelMapper),或者通过手动方式实现属性复制并添加适当的逻辑来避免无限递归。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值