Principles of mapstruct framework

I’m not going to go into the basic usage here, but I’m sure you know the basic usage, which is to get the attribute name by reflection and then assign it. We can also specify the transformation rules by using the mapping annotation. Here are some things to pay attention to through principle. Two classes:

@Data
class A{
	private String name;
	private String age;
}

@Data
class B{
	private String name;
	private String age;
	private String address;
}
Copy the code
// The set of B objects is converted to the set of A objects
List<A> bListToAList(List<B> bList);
Copy the code

The code above converts B to A, and the actual compiled code is as follows. It may be confusing that we did not declare the conversion of A single object, so how did it compile the object? This is because compile-time enhancements to the code add the conversion of A single object through reflection. Instead of being automatically generated every time, it first iterates through the entire object’s methods, using parameters and return values to determine if the required single object conversion method already exists. If it exists, use it.

	public A bToA(B b) {
        if (b== null) {
            return null;
        } else {
        	A a = new A();
            a.setName(b.getName());
            a.setAge(b.getAge());
            returna; }}public List<A> bListToAList(List<B> bList) {
        if (bList== null) {
            return null;
        } else {
            List<A> list = new ArrayList(bList.size());
            Iterator var3 = bList.iterator();

            while(var3.hasNext()) {
                B b = (B)var3.next();
                list.add(this.bToA(b));
            }
            returnlist; }}Copy the code

If we customize the property correspondence

// Object B is converted to object A
@Mappings({ @Mapping(source = "name", target = "name"), @Mapping(source = "address", target = "age") })
A bToA(B b);
// The set of B objects is converted to the set of A objects
List<A> bListToAList(List<B> bList);
Copy the code

The compiled code looks like this: We find that it uses our custom conversion rules

	public A bToA(B b) {
        if (b== null) {
            return null;
        } else {
        	A a = new A();
            a.setName(b.getName());
            a.setAge(b.getAddress());
            returna; }}public List<A> bListToAList(List<B> bList) {
        if (bList== null) {
            return null;
        } else {
            List<A> list = new ArrayList(bList.size());
            Iterator var3 = bList.iterator();

            while(var3.hasNext()) {
                B b = (B)var3.next();
                list.add(this.bToA(b));
            }
            returnlist; }}Copy the code

What happens if we write two methods whose names are different, but whose parameters are the same as the return value?

// Object B is converted to object A
@Mappings({ @Mapping(source = "name", target = "name"), @Mapping(source = "address", target = "age") })
A bToA(B b);
A bToANew(B b);
// The set of B objects is converted to the set of A objects
List<A> bListToAList(List<B> bList);
Copy the code

Ambiguous mapping Methods found for mapping collection element (Ambiguous mapping methods found for mapping collection elements) This is because the principle described above is to determine the method by the parameter and return value, when the class has the same parameter and return value method, so the error will be reported. QualifiedByName =’ qualifiedByName ‘; @named and @iterableMapping (qualifiedByName =”);

// Object B is converted to object A
@Mappings({ @Mapping(source = "name", target = "name"), @Mapping(source = "address", target = "age") })
@Named('bToA')
A bToA(B b);
@Named('bToANew')
A bToANew(B b);
// The set of B objects is converted to the set of A objects
@iterableMapping (qualifiedByName ='bToANew') List bListToAList(List bList);Copy the code

The compiled code is as follows:

	public A bToA(B b) {
        if (b== null) {
            return null;
        } else {
        	A a = new A();
            a.setName(b.getName());
            a.setAge(b.getAddress());
            returna; }}public A bToANew(B b) {
        if (b== null) {
            return null;
        } else {
        	A a = new A();
            a.setName(b.getName());
            a.setAge(b.getAge());
            returna; }}public List<A> bListToAList(List<B> bList) {
        if (bList== null) {
            return null;
        } else {
            List<A> list = new ArrayList(bList.size());
            Iterator var3 = bList.iterator();

            while(var3.hasNext()) {
                B b = (B)var3.next();
                list.add(this.bToANew(b));
            }
            returnlist; }}Copy the code