Author: Xiao Fu Ge
Blog: https://bugstack.cn
Original: https://mp.weixin.qq.com/s/Xq7oQg7dYESMYxHVnxX8Dw
Precipitate, share, and grow, so that you and others can gain something! 😄
I. Introduction
Why, your code is just usable?
How to write code without technical depth, lack of knowledge reserves, and lack of experience accumulation? Baidu ah, a problem that this search, a search that, no matter what kind of principle or for a scene, first paste into your own projects, see, run, and run on the line . Then such code is only available to the extent of delivery, there is no certain quality assurance at all, let alone data structure, algorithm logic, and design patterns. Then look at the programming materials and brush the LeetCode.
What do you say when you feel that you have read a lot of information and can't use it? The real volume, you have learned this. But in fact I did not feel the depth of excavation technology, carding a full range of knowledge, a little hard a little harvest in volume . On the contrary, watching technical videos is as easy as watching a movie. If you don’t write a case, you think it’s cool to read a book. It’s meaningless, lack of brainpower, and mechanical physical repetition. It’s a volume or even a volume.
It's like letting you use a property copy tool to convert vo to dto. Which one do you use, is it Apache or Spring, or something else, which is the most efficient? Next, let’s verify with data and provide a comparison of the use of various cases.
Two, performance test comparison
In the process of Java system engineering development, there will be object conversions between various layers, such as VO, DTO, PO, VO, etc., and if it is manual get、set
it is too time-consuming and may be incorrect in operation, so choosing an automated tool will More convenient.
At present, I have sorted out 12 kinds of object attribute conversions, including: ordinary getset, json2Json, Apache attribute copy, Spring attribute copy, bean-mapping, bean-mapping-asm, BeanCopier, Orika, Dozer, ModelMapper, JMapper, MapStruct Next we tested the performance time comparison of these 11 attribute conversion operations at 100 times,
1000 times,
10000 times,
100,000 times, and
1 million times.
BeanUtils.copyProperties
is the most common tool class in your code, but as long as you don't use it in the wrongApache
, but use the one provided by Spring, it will basically not have much impact on performance.- But if the performance is better, it can replace the manual
get、set
, orMapStruct
better, because it itself generatesget、set
code at compile time, just like we writeget、set
- Some other component packages are mainly based on
AOP
,ASM
,CGlib
, so there will be corresponding performance losses.
Three, 12 conversion cases
source code : https://github.com/fuzhengwei/guide-vo2dto
Description : Create the interfaces.assembler package under the case project, define the IAssembler<SOURCE, TARGET>#sourceToTarget(SOURCE var)
interface, and provide different ways of object conversion operation class implementation. You can download and run debugging directly during the learning process.
1. get\set
@Component
public class GetSetAssembler implements IAssembler<UserVO, UserDTO> {
@Override
public UserDTO sourceToTarget(UserVO var) {
UserDTO userDTO = new UserDTO();
userDTO.setUserId(var.getUserId());
userDTO.setUserNickName(var.getUserNickName());
userDTO.setCreateTime(var.getCreateTime());
return userDTO;
}
}
- recommended : ★★★☆☆
- Performance : ★★★★★
- means : handwriting
- Comments : In fact, this method is also the most commonly used daily, the performance is definitely leveraged, but it is a bit troublesome to operate. Especially when a lot of attribute VO objects are converted to DTO objects. But in fact, there are some quick operation methods. For example, you can select all attributes by Shift+Alt, Shift+Tab merge them into one column, and then use Alt to select this column, batch operation paste
userDTO.set
and the initial letter of the shortcut key capitalized attributes, and finally switch Add parentheses and semicolons to the end, and the final formatting is done.
2. json2Json
@Component
public class Json2JsonAssembler implements IAssembler<UserVO, UserDTO> {
@Override
public UserDTO sourceToTarget(UserVO var) {
String strJson = JSON.toJSONString(var);
return JSON.parseObject(strJson, UserDTO.class);
}
}
- recommended : ☆☆☆☆☆
- Performance : ★☆☆☆☆
- means : convert the object to a JSON string, and then convert the JSON to another object
- reviews : This is probably a bit burnt!
3. Apache copyProperties
@Component
public class ApacheCopyPropertiesAssembler implements IAssembler<UserVO, UserDTO> {
@Override
public UserDTO sourceToTarget(UserVO var) {
UserDTO userDTO = new UserDTO();
try {
BeanUtils.copyProperties(userDTO, var);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return userDTO;
}
}
- recommended : ☆☆☆☆☆
- Performance : ★☆☆☆☆
- means : Introspector mechanism obtains the attributes of the class to perform assignment operations
- Comments : There are pits, compatibility is bad, not recommended
4. Spring copyProperties
@Component
public class SpringCopyPropertiesAssembler implements IAssembler<UserVO, UserDTO> {
@Override
public UserDTO sourceToTarget(UserVO var) {
UserDTO userDTO = new UserDTO();
BeanUtils.copyProperties(var, userDTO);
return userDTO;
}
}
- recommended : ★★★☆☆
- Performance : ★★★★☆
- means : Introspector mechanism obtains the attributes of the class to perform assignment operations
- Comments : The same is the reflected property copy. The copyProperties provided by Spring is much easier to use than Apache. As long as you don't make mistakes, there will be no problems.
5. Bean Mapping
@Component
public class BeanMappingAssembler implements IAssembler<UserVO, UserDTO> {
@Override
public UserDTO sourceToTarget(UserVO var) {
UserDTO userDTO = new UserDTO();
BeanUtil.copyProperties(var, userDTO);
return userDTO;
}
}
- recommended : ★★☆☆☆
- Performance : ★★★☆☆
- means : attribute copy
- reviews : average performance
6. Bean Mapping ASM
@Component
public class BeanMappingAssembler implements IAssembler<UserVO, UserDTO> {
@Override
public UserDTO sourceToTarget(UserVO var) {
UserDTO userDTO = new UserDTO();
BeanUtil.copyProperties(var, userDTO);
return userDTO;
}
}
- recommended : ★★★☆☆
- Performance : ★★★★☆
- Means : Implementation based on ASM bytecode framework
- Comments : Compared with ordinary Bean Mapping, the performance has been improved and it can be used.
7. BeanCopier
@Component
public class BeanCopierAssembler implements IAssembler<UserVO, UserDTO> {
@Override
public UserDTO sourceToTarget(UserVO var) {
UserDTO userDTO = new UserDTO();
BeanCopier beanCopier = BeanCopier.create(var.getClass(), userDTO.getClass(), false);
beanCopier.copy(var, userDTO, null);
return userDTO;
}
}
- recommended : ★★★☆☆
- Performance : ★★★★☆
- means : generate get and set methods based on CGlib bytecode operation
- Comments : The overall performance is very good, the use is not complicated, you can use
8. Orika
@Component
public class OrikaAssembler implements IAssembler<UserVO, UserDTO> {
/**
* 构造一个MapperFactory
*/
private static MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
static {
mapperFactory.classMap(UserDTO.class, UserVO.class)
.field("userId", "userId") // 字段不一致时可以指定
.byDefault()
.register();
}
@Override
public UserDTO sourceToTarget(UserVO var) {
return mapperFactory.getMapperFacade().map(var, UserDTO.class);
}
}
- official website : https://orika-mapper.github.io/orika-docs/
- recommended : ★★☆☆☆
- Performance : ★★★☆☆
- means : Generate mapping object based on bytecode
- Comments : The test performance is not too outstanding, if you use it, you need to optimize the construction of MapperFactory into a Bean object
9. Dozer
@Component
public class DozerAssembler implements IAssembler<UserVO, UserDTO> {
private static DozerBeanMapper mapper = new DozerBeanMapper();
@Override
public UserDTO sourceToTarget(UserVO var) {
return mapper.map(var, UserDTO.class);
}
}
- official website : http://dozer.sourceforge.net/documentation/gettingstarted.html
- recommended : ★☆☆☆☆
- Performance : ★★☆☆☆
- means : attribute mapping framework, copy objects recursively
- Comments : performance is a bit poor, not recommended
10. ModelMapper
@Component
public class ModelMapperAssembler implements IAssembler<UserVO, UserDTO> {
private static ModelMapper modelMapper = new ModelMapper();
static {
modelMapper.addMappings(new PropertyMap<UserVO, UserDTO>() {
@Override
protected void configure() {
// 属性值不一样可以自己操作
map().setUserId(source.getUserId());
}
});
}
@Override
public UserDTO sourceToTarget(UserVO var) {
return modelMapper.map(var, UserDTO.class);
}
}
- official website : http://modelmapper.org
- recommended : ★★★☆☆
- Performance : ★★★☆☆
- means : based on ASM bytecode implementation
- Comments : The performance is good when the number of converted objects is small, if the objects are converted in large quantities at the same time, the performance will decrease
11. JMapper
JMapper<UserDTO, UserVO> jMapper = new JMapper<>(UserDTO.class, UserVO.class, new JMapperAPI()
.add(JMapperAPI.mappedClass(UserDTO.class)
.add(JMapperAPI.attribute("userId")
.value("userId"))
.add(JMapperAPI.attribute("userNickName")
.value("userNickName"))
.add(JMapperAPI.attribute("createTime")
.value("createTime"))
));
- official website : https://github.com/jmapper-framework/jmapper-core/wiki
- recommended : ★★★★☆
- Performance : ★★★★★
- means : Elegance, high performance and robustness all in one java bean mapper
- Comments : The speed is really ok, but combined with SpringBoot, it feels a little troublesome, maybe the posture is wrong
12. MapStruct
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE, unmappedSourcePolicy = ReportingPolicy.IGNORE)
public interface UserDTOMapping extends IMapping<UserVO, UserDTO> {
/** 用于测试的单例 */
IMapping<UserVO, UserDTO> INSTANCE = Mappers.getMapper(UserDTOMapping.class);
@Mapping(target = "userId", source = "userId")
@Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
@Override
UserDTO sourceToTarget(UserVO var1);
@Mapping(target = "userId", source = "userId")
@Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
@Override
UserVO targetToSource(UserDTO var1);
}
- official website : https://github.com/mapstruct/mapstruct
- recommended : ★★★★★
- Performance : ★★★★★
- means : generate the corresponding get and set directly at compile time, just like handwritten code
- Comments : It is very fast, does not need to be processed during runtime, and is easy to use when combined into the framework
Four, summary
- In fact, the operation of object attribute conversion is nothing more than processing based on reflection, AOP, CGlib, ASM, and Javassist at compile time and runtime. A good idea is to generate the corresponding get and set before compiling, just like handwriting. .
- So I recommend MapStruct, which I like, because it is more comfortable to use. One is from the scalability, ease of use and compatibility.
- No matter what kind of use, you have to do a complete test and verification. Don't just copy and paste when you come up. Otherwise, you may have dug the hole early. Of course, it may not be which brother will fill the hole.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。