This is the 19th day of my participation in the August Wenwen Challenge.More challenges in August
Today is not about the design pattern, has been insisting on watching my design pattern people may know that the design pattern column has not finished speaking, the reason why I do not speak today, is thinking about the last to keep is the most important, in our ordinary actual combat process use the most, so I want to design. Try to make everyone rave. Haha without further ado, today we’re not talking about design patterns.
(Check it out at the end of this article for those interested, and I’ll post a link.)
Or more nagging a few words, welcome to pay attention to, like, I will continue to output dry goods, you can also click on my avatar, view the history of dry goods!
Copy the object
Why copy objects? As we all know, in daily development, services A, B, C may call services B, and the interface parameter values are roughly the same. Come over here. DO, DTO, VO, etc., these entities need to be transposed. Writing mapping transformation code is a tedious, repetitive and error-prone task.
(Tip: The interface is generally connected with DTO, return to VO return as far as possible, then this will involve conversion, such as DTO POJO)
Let’s look at several ways to copy objects, and who is the most “SAO” that one
BeanUtil class
The first thing you might think you’re going to use the most is apache’s BeanUtil class, and yes, that’s what I used when I first started working.
org.apache.commons.beanutils.BeanUtils.copyProperties(do, entity);
Copy the code
Q: What’s wrong with that?
A: BeanUtil. CopyProperties () combines get and set by hand. For simple transformations, use BeanUtil directly, and for complex transformations, write get and set by hand. The pain point of this solution is that the code is inefficient, redundant and slightly ugly, and BeanUtil is not performing well because it uses reflection invoke to assign values.
It is suitable only for scenarios with a small number of beans, a small amount of content, and infrequent transformations.
And the Ali Development statute makes it clear
So remember to use it here…
Let’s look at the second one
Fastjson
Yeah, that’s right. Ali’s Fastjson works, too.
// This way, basically we take the string to json use
StudentsDTO entity = JSON.parseObject(JSON.toJSONString(studentsDO), StudentsDTO.class);
Copy the code
This is done by generating an intermediate JSON-formatted string and then converting it to the target object.
The performance is probably not as good or worse than the first one, and because of the jSON-formatted strings that are generated in the middle, gc is very frequent if there are too many conversions, and there is not enough support for complex scenarios, so it is rarely used.
So the second one is not the sluttiest one. Keep reading!
Spring.BeanUtils
This solution has a lot of optimizations for Apache’s BeanUtils, and the overall performance is improved a lot. However, the reflection implementation is still not as good as the native code processing, and the support for complex scenarios is not enough.
Below I screenshot source code roughly look
The core is in this for loop, which has improved performance but is still not the sluttiest.
Mapstruct
You may have seen this frame more or less, but after you finish reading it, you will find that I wipe the thief “SAO”.
Our code actual combat demo a wave:
Maven is introduced into
Mapstruct-jdk1.8: mapstruct-jdk1.8: mapstruct-jdk1.8: mapstruct-jdk1.8
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4. 0.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4. 0.Final</version>
</dependency>
Copy the code
Note: When introduced here, try not to conflict with the Sweeager package, which also contains mapstruct. If you have any questions, please leave a comment below and we’ll discuss:
Introduction of actual combat
For example, we DTO and BO (advise Lombok)
@Data
public class Students {
private String name;
private int age;
private int sex; //0 indicates male. 1: indicates female
}
@Data
public class StudentsDTO {
private String name;
private int age;
private int sex; //0 indicates male. 1: indicates female
public StudentsDTO(a){}
// constructor
public StudentsDTO(String name,int age,int sex){
this.name = name;
this.age = age;
this.sex = sex; }}Copy the code
Defines Mapper, which is an interface class
import org.mapstruct.Mapper;
// All operations are performed on this annotated mapper
@Mapper(componentModel = "spring")
public interface StudentsMapper {
//dto 转 BO
Students DTOToStBo(StudentsDTO st);
}
Copy the code
ComponentModel = “Spring” represents the use of spring bean injection by generating a Mapper annotation plus spring configuration, will automatically generate a bean, directly using bean injection can be accessed.
Mapper describes the mapping, and mapstruct will generate the implementation class based on this description when editing:
-
When an attribute has the same name as its target entity copy, it is implicitly mapped.
-
When attributes in the target entity have different names, you can specify their names using the @Mapping annotation
Yes, you can use the @mapping annotation to specify the attribute name when the attribute name is inconsistent
@Mapper(componentModel = "spring")
public interface StudentsMapper {
// For example, in the student class, the class attributes are different
@Mapping(source = "className", target = "grades")
Students DTOToStBo(StudentsDTO st);
}
Copy the code
How do I call it. Use by generating static instances through the Mappers factory. (I talked about factory mode and singleton mode earlier and you can click on the picture)
import org.mapstruct.factory.Mappers
@Mapper(componentModel = "spring")
public interface StudentsMapper {
// Static instantiation
StudentsMapper INSTANCE = Mappers.getMapper(StudentsMapper.class);
// For example, in the student class, the class attributes are different
@Mapping(source = "className", target = "grades")
Students DTOToStBo(StudentsDTO st);
}
Copy the code
StudentsDTO stDTO = new StudentsDTO("Zhang".18.1);
Students students = StudentsMapper.INSTANCE.DTOToStBo(stDTO);
System.out.println("students.name -> "+students.getName());
// Output: zhang SAN
Copy the code
OK completes the conversion assignment, and we’ll talk about how it works
The principle of
First, the @mapper annotation, which is the implementation class impL that is generated when the code is compiled, and which actually implements the object data assignment.
When compiled, you can go to the target package to see:
Or just go in there and implement the class
See, the core is here, the thief.
The reason we used gatMapper above is to get this implementation class
OK, that’s all for today.
overtones
Thank you for reading, if you feel that you have learned something, please like, follow. Also welcome to have a question we comment below exchange
Come on! See you next time! Here are some of this month’s best design patterns:
Singletons of design patterns
Factory patterns for design patterns
The Builder pattern of design patterns
Proxy patterns for design patterns
Visitor patterns for design patterns
Adapter pattern for design pattern
Design pattern of the command pattern
Java state pattern | monitoring state change anytime and anywhere
Java observer pattern | how to notice things change
Java mode | how to record history information memorandum
Java iterator pattern model | how to access each element
Java the flyweight pattern | how to share the object
Java interpreter pattern | custom rules implementation logic
The Java bridge model | abstract binding with different implementations