
// 1. 获取目标属性描述符(缓存)
PropertyDescriptor[] targetPds = getCachedPd(targetClass);
for (PropertyDescriptor pd : targetPds) {
// 2. 直接读取源属性值(无转换)
Object value = pd.getReadMethod().invoke(source);
// 3. 直接写入目标属性
pd.getWriteMethod().invoke(target, value);
}
// 1. 动态获取属性描述符(无稳定缓存)
PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors(orig);
for (PropertyDescriptor pd : pds) {
// 2. 读取属性(额外反射调用)
Object value = PropertyUtils.getProperty(orig, pd.getName());
// 3. 转换器查找(性能黑洞!)
Converter converter = ConvertUtils.lookup(pd.getPropertyType());
Object convertedValue = converter.convert(value);
// 4. 写入属性(再次反射)
PropertyUtils.setProperty(dest, pd.getName(), convertedValue);
}

-
MapStruct:12ms
-
Spring:35ms
-
Orika:42ms
-
ModelMapper:68ms
-
Apache:210ms
-
MapStruct:15ms
-
Orika:55ms
-
ModelMapper:120ms
-
Apache:480ms
-
Spring:不支持
@Mapper
publicinterfaceUserConverter{
// 编译时生成具体实现类
UserConverter INSTANCE = Mappers.getMapper(UserConverter.class);
@Mapping(source = "registerDate", target = "registerTime")
UserDTO toDTO(UserEntity entity);
// 自定义日期转换(无运行时开销)
default LocalDateTime dateToLocalDateTime(Date date){
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
}
}
// 使用示例
UserDTO dto = UserConverter.INSTANCE.toDTO(entity);
MapperFactory factory = new DefaultMapperFactory.Builder().build();
factory.classMap(Source.class, Target.class)
.field("createDate", "createTime")
.byDefault()
.register();
MapperFacade mapper = factory.getMapperFacade();
Target target = mapper.map(source, Target.class);
@Configuration
publicclassConverterConfigimplementsWebMvcConfigurer{
@Override
publicvoidaddFormatters(FormatterRegistry registry){
registry.addConverter(new DateToLocalDateTimeConverter());
}
// 线程安全的转换器实现
publicstaticclassDateToLocalDateTimeConverter
implementsConverter<Date, LocalDateTime> {
@Override
public LocalDateTime convert(Date source){
return source.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
}
}
}
// 在任意位置使用
@Autowired ConversionService conversionService;
publicvoidprocess(UserInput input){
User user = new User();
conversionService.convert(input, User.class);
}
publicclassCachedConverterimplementsConverter{
// 双检锁缓存设计
privatestaticfinal Map<Class<?>, Converter> CACHE = new ConcurrentHashMap<>();
@Override
public Object convert(Class type, Object value){
Converter converter = CACHE.get(type);
if (converter == null) {
synchronized (this) {
converter = CACHE.computeIfAbsent(type,
t -> createConverter(t));
}
}
return converter.convert(type, value);
}
private Converter createConverter(Class<?> type){
if (LocalDateTime.class.equals(type)) {
returnnew DateToLocalDateTimeConverter();
}
// 其他类型转换器...
}
}
publicclassBatchBeanUtils{
// 预编译属性访问器
privatestaticfinal Map<Class<?>, PropertyDescriptor[]> DESCRIPTOR_CACHE = new ConcurrentHashMap<>();
publicstatic <T> voidcopyList(List<?> sources, List<T> targets,
Class<T> targetClass){
PropertyDescriptor[] targetPds = DESCRIPTOR_CACHE.computeIfAbsent(
targetClass,
clz -> BeanUtils.getPropertyDescriptors(clz)
);
for (int i = 0; i < sources.size(); i++) {
T target = targets.get(i);
Object source = sources.get(i);
// 自定义优化拷贝逻辑...
}
}
}

@JMapper({
@JMap(value = "registerDate", target = "registerTime"),
@JMap(value = "address.city", target = "city")
})
publicinterfaceUserMapper{
UserDTO toDTO(UserEntity entity);
}
// 自动生成扩展方法
@Extension
publicclassUserEntityExtensions{
publicstatic UserDTO toDTO(@This UserEntity entity){
UserDTO dto = new UserDTO();
dto.setName(entity.getName());
dto.setRegisterTime(entity.getRegisterDate().toLocalDateTime());
return dto;
}
}
// 调用方式
UserDTO dto = userEntity.toDTO();
-
基础层: 属性赋值(BeanUtils)
-
业务层: 类型转换+格式处理(Converter)
-
领域层: 对象语义映射(DTO Assembler)
-
元编程层: 编译时代码生成(MapStruct)
-
接口层: 使用MapStruct处理DTO转换
-
领域层: 专用Assembler实现业务语义映射
-
基础设施: Spring Conversion处理基础类型转换
往期推荐
IDEA 实战:查看 Maven 依赖树与解决 Jar 包冲突
工作中最常用的6种API网关
SpringBoot中常用的工具类库及其使用示例
再见Navicat、XShell!一款高颜值的数据库、SSH、Docker管理工具!
SpringBoot一行代码搞定请假审批流程,摸鱼时间翻倍!
凌晨两点,我因为 14 寸笔记本的 9 号字体把线上事故从 P0 拖成了 P1

