当前位置:网站首页>Why is BeanUtils not recommended?

Why is BeanUtils not recommended?

2022-06-25 23:18:00 Java technology stack

author : Mingmingruyue senior \
source :blog.csdn.net/w605283073/article/details/107371462

I mentioned in the column before “ Attribute copying tools are not recommended ”, It is recommended to directly define transformation classes and methods IDEA Plug in auto fill get / set function .

The main reason for not recommending is :

Some attribute copying tools have poor performance Some attribute copying tools have “BUG” Using the attribute copy tool is prone to some hidden dangers ( Later examples will talk about )

2 Example

First of all, the company has encountered commons Bag BeanUtils A real case of poor property copy performance , Then the colleague changed to Spring Of BeanUtils The performance is much better , If you are interested, you can use the performance test framework or benchmark framework to compare , There is no comparison here .

Now let's see Spring Of BeanUtils What are the problems with copying the properties of :

import lombok.Data;
import java.util.List;

@Data
public class A {
    private String name;

    private List<Integer> ids;
}
@Data
public class B {
    private String name;

    private List<String> ids;
}
import org.springframework.beans.BeanUtils;

import java.util.Arrays;

public class BeanUtilDemo {
    public static void main(String[] args) {
        A first = new A();
        first.setName("demo");
        first.setIds(Arrays.asList(1, 2, 3));

        B second = new B();
        BeanUtils.copyProperties(first, second);
        for (String each : second.getIds()) {//  Type conversion exception 
            System.out.println(each);
        }
    }
}

When you run the above example , A type conversion exception occurs .

At the break point, you can see , After the attribute is copied B Type of second In the object ids Still for Integer type :

img

If not converted to a string , Print directly , No errors are reported .

Use CGlib Not defined in Converter Similar problems will be encountered in the case of :

import org.easymock.cglib.beans.BeanCopier;

import java.util.Arrays;

public class BeanUtilDemo {
    public static void main(String[] args) {
        A first = new A();
        first.setName("demo");
        first.setIds(Arrays.asList(1, 2, 3));

        B second = new B();
        final BeanCopier beanCopier = BeanCopier.create(A.class, B.class, false);
        beanCopier.copy(first,second,null);

        for (String each : second.getIds()) {//  Type conversion exception 
            System.out.println(each);
        }
    }
}

Again , The problem is exposed at runtime .

Let's take a look mapstruct:

import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper
public interface Converter {
    Converter INSTANCE = Mappers.getMapper(Converter.class);

    B aToB(A car);
}
import java.util.Arrays;

public class BeanUtilDemo {
    public static void main(String[] args) {
        A first = new A();
        first.setName("demo");
        first.setIds(Arrays.asList(1, 2, 3));

        B second = Converter.INSTANCE.aToB(first);
        for (String each : second.getIds()) {//  normal 
            System.out.println(each);
        }
    }
}

Can succeed in A in List<Integer> To B Medium List<String> type . Let's look at the compiled Converter Implementation class :

import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
import org.springframework.stereotype.Component;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    comments = "version: 1.3.1.Final, compiler: javac, environment: Java 1.8.0_202 (Oracle Corporation)"
)
@Component
public class ConverterImpl implements Converter {

    @Override
    public B aToB(A car) {
        if ( car == null ) {
            return null;
        }

        B b = new B();

        b.setName( car.getName() );
        b.setIds( integerListToStringList( car.getIds() ) );

        return b;
    }

    protected List<String> integerListToStringList(List<Integer> list) {
        if ( list == null ) {
            return null;
        }

        List<String> list1 = new ArrayList<String>( list.size() );
        for ( Integer integer : list ) {
            list1.add( String.valueOf( integer ) );
        }

        return list1;
    }
}

Automatically helped us with the conversion , We may not realize that the types are inconsistent .

If we were A Add one to the class String number attribute , stay B Add one to the class Long number attribute , Use mapstruect When number When it is set to non numeric type, it will report .NumberFormatException.

@Override
public B aToB(A car) {
    if ( car == null ) {
        return null;
    }

    B b = new B();

    b.setName( car.getName() );
    if ( car.getNumber() != null ) { //  Here's the problem 
        b.setNumber( Long.parseLong( car.getNumber() ) );
    }
    b.setIds( integerListToStringList( car.getIds() ) );

    return b;
}

Use cglib By default, there is no mapping number attribute ,B Medium number by null. If you define the converter manually , Use IDEA plug-in unit ( Such as generateO2O) Automatic conversion :

public final class A2BConverter {

    public static B from(A first) {
        B b = new B();
        b.setName(first.getName());
        b.setIds(first.getIds());
        return b;
    }
}

This problem can be found very clearly in the coding phase :

img

3 Conclusion

because Java Generics are actually compile time checks , Post compilation generic erasure , Causes the runtime to List<Integer> and List<String> All are List type , It can be assigned normally . This leads to when using many attribute mapping tools , It is not easy to make obvious errors at compile time .

mapstruct Custom annotation processor , The generic types on both sides of the map can be read at compile time , Then map . But this mapping is also terrible , Sometimes we define the wrong type due to carelessness and other reasons , Automatically helped us with the conversion , It will bring a lot of side effects .

The performance of various attribute mapping tools has been briefly compared before , give the result as follows :

img

Therefore, use attribute conversion tools with caution , If possible, it is recommended to customize the conversion class , Use IDEA Plug in auto fill , Very efficient , A or B Any property type in does not match , Even delete an attribute , Errors can be reported at the compilation stage , And directly call get set The efficiency is also very high .

Recent hot article recommends :

1.1,000+ Avenue Java Arrangement of interview questions and answers (2022 The latest version )

2. Explode !Java Xie Cheng is coming ...

3.Spring Boot 2.x course , It's too complete !

4.20w Programmer red envelope cover , Get it quickly ...

5.《Java Development Manual ( Song Mountain version )》 The latest release , Download it quickly !

I think it's good , Don't forget to like it + Forward !

原网站

版权声明
本文为[Java technology stack]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202180927564023.html