在企業級開發中,ActionForm 與領域模型、DTO 與 Entity、VO 與 PO 之間頻繁需要屬性拷貝。手寫幾十行 setXxx(getXxx()) 不僅枯燥,還易出錯。本文對比三種主流方案:Apache BeanUtils、Spring BeanUtils、反射手寫實現,並給出性能與適用場景建議。
// 依賴:commons-beanutils.jar BeanUtils.copyProperties(dest, src); // 目標在前,源在後
// 依賴:spring-beans.jar(Spring 核心模組已包含) BeanUtils.copyProperties(src, dest); // 源在前,目標在後
文章提供的 BeanUtil2.CopyBeanToBean 展示核心邏輯:
public static Object CopyBeanToBean(Object src, Object dest) throws Exception {
Method[] srcMethods = src.getClass().getMethods();
Method[] destMethods = dest.getClass().getMethods();
for (Method srcM : srcMethods) {
if (srcM.getName().startsWith("get")) {
String prop = srcM.getName().substring(3); // 屬性名
for (Method destM : destMethods) {
if (destM.getName().equals("set" + prop)) {
Object value = srcM.invoke(src);
destM.invoke(dest, value);
break;
}
}
}
}
return dest;
}
| 方案 | 耗時(ms) | 相對性能 |
|---|---|---|
| 手寫 get/set | ~15 | 1.0x (基準) |
| Spring BeanUtils | ~120 | 8x |
| Apache BeanUtils | ~450 | 30x |
| 反射手寫(無緩存) | ~800 | 50x+ |
結論:高頻熱路徑請手寫或用 MapStruct(編譯期生成代碼,性能接近手寫);一般業務用 Spring BeanUtils;複雜嵌套用 Apache BeanUtils。
@Mapper
public interface UserMapper {
UserDTO toDTO(User entity);
User toEntity(UserDTO dto);
}