如何通过Spring机制实现无需手动映射公共字段的现有对象属性拷贝Mapper
方案解答
完全可以通过Spring生态的相关能力实现你的需求,不需要手动编写100个公共字段的映射逻辑,同时支持传入已有对象直接做属性拷贝、不生成新对象。
方案1:直接使用Spring自带BeanUtils(零额外依赖,最简单)
Spring核心包自带的org.springframework.beans.BeanUtils已经原生提供了你要的方法签名,底层通过反射自动匹配同名字段做拷贝,继承自父类C的公共字段只要字段名、类型匹配就会自动映射,不需要手动编码。
使用示例:
import org.springframework.beans.BeanUtils; public class CustomMapper { // 符合你要求的入参格式,无返回值,直接修改传入的target对象 public void mapMe(B source, A target) { // 自动拷贝所有匹配字段,最后一个可变参数可传入要忽略的字段名 BeanUtils.copyProperties(source, target); } // 通用形式也可以直接实现 public <S, T> void mapMe(S source, T target) { BeanUtils.copyProperties(source, target); } }
注意事项:
- 该工具是浅拷贝,若字段包含复杂引用类型,只会拷贝引用地址
- 仅支持字段名、类型完全一致的字段自动映射,不匹配的字段会被自动忽略
- 适合普通业务场景使用,超大批量映射场景性能略低于编译期生成代码的方案
方案2:MapStruct配合Spring(高性能,支持自定义映射规则)
如果你除了公共字段之外,还有少量A、B自有字段需要特殊映射规则,可以用MapStruct框架,它支持编译期生成Mapper实现代码,不需要手写映射逻辑,同时可以直接注册为Spring Bean。
使用步骤:
- 引入MapStruct依赖(Spring Boot项目可直接引入对应starter)
- 定义Mapper接口:
import org.mapstruct.Mapper; import org.mapstruct.MappingTarget; // 指定componentModel = "spring",生成的实现类会自动注册为Spring Bean,可直接注入使用 @Mapper(componentModel = "spring") public interface AbMapper { // 继承自C的100个公共字段自动匹配映射,不需要手动编写逻辑 void mapMe(B source, @MappingTarget A target); // 通用形式也支持 <S, T> void mapGeneric(S source, @MappingTarget T target); }
优势:
- 编译期生成代码,无反射开销,性能和手写代码一致
- 支持自定义字段映射、类型转换、忽略规则,灵活性更高
- 字段不匹配时编译期就会抛出提示,避免运行期异常
通用注意事项
- 两种方案都要求待映射的字段有符合JavaBean规范的public getter/setter方法
- 导包时注意不要和Apache Commons的
BeanUtils混淆,Spring自带的实现性能更好、无额外依赖
内容的提问来源于stack exchange,提问作者michealAtmi
相关产品推荐
相关产品推荐

